Docker 기초
Docker 기초
컨테이너는 운영체제 위에 격리된 사용자 공간을 띄워 같은 모습의 애플리케이션을 어디서든 돌리는 길. Docker 는 이 컨테이너를 표준 도구로 묶어 대중화한 결정적 계기. 이 글은 Docker 의 출자 · 이미지 / 컨테이너 / 레이어 / 볼륨 / 네트워크 같은 기본 개념 · Dockerfile 핵심 명령 · 멀티스테이지 빌드 · BuildKit · 이웃 도구를 정리합니다.
1. Docker 에 대한 이야기
| 사건 | 시기 |
|---|---|
| dotCloud 가 내부 도구로 출발 (Solomon Hykes 등) | 2008–2013 |
| Docker 오픈소스 공개 (PyCon 2013) | 2013-03 |
| Docker 0.9 — libcontainer 도입 (LXC 의존 제거) | 2014 |
| Docker 1.0 | 2014-06 |
| OCI (Open Container Initiative) 발족 — Linux Foundation | 2015 |
| Multi-stage build (Dockerfile) | Docker 17.05 / 2017 |
| BuildKit 안정화 | 2018 |
| Docker Desktop 라이선스 변경 (대기업 유료) | 2021 |
OCI 가 표준화한 두 사양 — 이미지 사양 과 런타임 사양 — 덕분에 Docker 외 런타임 (containerd · CRI-O · Podman) 이 같은 이미지를 다룹니다.
2. 핵심 어휘
| 용어 | 의미 |
|---|---|
| 이미지 | 실행 가능한 파일시스템 스냅샷 + 메타데이터. 불변. |
| 컨테이너 | 이미지에서 띄운 프로세스 격리 단위. 변경은 위쪽 레이어에. |
| 레이어 | 이미지의 변경 단위. 캐시·재사용 단위. |
| 볼륨 | 컨테이너 외부 데이터 영속화. |
| 네트워크 | 컨테이너 간 통신 경계 (bridge · host · overlay). |
| 레지스트리 | 이미지 저장소 (Docker Hub · ghcr.io · ECR). |
3. 이미지와 레이어
Dockerfile 의 각 명령 (RUN · COPY · ADD) 이 하나의 레이어. 같은 명령 + 같은 입력이면 캐시 재사용. 레이어 순서를 잘 짜는 것이 빌드 시간의 큰 차이를 만듭니다.
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci # 의존만 변하면 여기서 캐시 무효화
COPY . . # 소스만 변할 때는 위 레이어 재사용
CMD ["node", "server.js"]
4. Dockerfile 핵심 명령
| 명령 | 역할 |
|---|---|
FROM |
베이스 이미지. 멀티스테이지에서는 여러 번. |
WORKDIR |
이후 명령의 현재 디렉터리. |
COPY / ADD |
파일 복사. ADD 는 URL · tar 자동 해제. 보통 COPY 권장. |
RUN |
빌드 시 실행. 셸 모드 vs exec 모드. |
ENV |
환경변수. 이미지에 고정. |
EXPOSE |
메타데이터 (문서화). 실제 포트 매핑은 런타임. |
CMD |
기본 실행 명령. |
ENTRYPOINT |
컨테이너의 진입점. CMD 와 결합 가능. |
CMD 는 기본 인자, ENTRYPOINT 는 고정 명령. 두 가지 결합 — ENTRYPOINT ["node"] CMD ["server.js"] 처럼 쓰면 인자만 바꿔 끼울 수 있음.
5. 멀티스테이지 빌드
빌드 단계와 런타임 단계를 분리해 최종 이미지를 가볍게.
FROM node:22 AS build
WORKDIR /src
COPY . .
RUN npm ci && npm run build
FROM node:22-slim
WORKDIR /app
COPY --from=build /src/dist ./dist
COPY --from=build /src/node_modules ./node_modules
CMD ["node", "dist/server.js"]
빌드 도구 · 소스 · 테스트 산출물이 최종 이미지에 들어가지 않습니다.
6. BuildKit
빌드 엔진 재작성으로, 병렬 실행 · 캐시 마운트 · secret 마운트 제공.
# syntax=docker/dockerfile:1.7
RUN --mount=type=cache,target=/root/.npm \
npm ci
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm publish
docker buildx 는 BuildKit 위에서 멀티 아키텍처 (arm64 / amd64) 빌드, 원격 빌더 같은 기능을 제공.
7. 다른 도구
| 도구 | 메모 |
|---|---|
| Podman | Red Hat 주도. 데몬 없는 모델. Docker CLI 호환. |
| containerd | Docker 가 분리해 CNCF 에 기증한 런타임. Kubernetes 가 표준 채택. |
| nerdctl | containerd 의 Docker 호환 CLI. |
| LXC · LXD | 리눅스 컨테이너의 오래된 형태. 시스템 컨테이너 강조. |
| Buildah | Podman 진영의 빌더. Dockerfile 없이도 가능. |
8. 베이스 이미지 선택지
- alpine — 크기가 작음 (수 MB). musl libc. 일부 glibc 기반 바이너리와 호환 문제가 자주.
- distroless (Google) — OS 도구 없이 런타임만. 보안 표면 축소.
- scratch — 완전히 빈 이미지. 정적 바이너리 (예: Go) 에 어울림.
- slim 변형 (
debian:slim·node:slim) — 균형점.
9. 자주 쓰는 모양
.dockerignore — .gitignore 와 비슷. 빌드 컨텍스트 축소로 빌드 시간 · 이미지 크기 감소.
node_modules
.git
*.log
.env*
비루트 사용자 — 컨테이너 내부 root 권한 노출 축소:
RUN useradd -m -u 10001 app
USER app
헬스체크 — 오케스트레이터 (compose · k8s) 가 기동 · 재시작 판단에 활용:
HEALTHCHECK --interval=30s --timeout=3s CMD curl -fsS http://localhost:8080/health || exit 1
10. 자주 걸리는 자리
COPY . . 의 캐시 무효화 — 소스 한 번 바뀌면 의존 설치 단계까지 다시 돌음. 의존 파일을 먼저 복사하는 순서가 정석.
컨테이너 안의 1번 프로세스 시그널 처리 — npm start 같은 래퍼는 SIGTERM 을 자식에게 잘 전달 못 할 수 있음. exec 모드 (CMD ["node", "server.js"]) 또는 tini.
이미지 크기 — node_modules · 빌드 캐시 · OS 패키지 잔재. 멀티스테이지 + slim / distroless 베이스로 큰 차이.
Windows 와 Linux 컨테이너 혼동 — Docker Desktop 의 모드 전환에 따라 베이스 이미지의 OS 가 달라짐. Windows 에서는 daemon.json · WSL2 백엔드 설정 확인.
latest 태그 — 재현 가능성이 깨짐. 명시적 버전 태그 · digest 핀 권장.
같은 태그로 재빌드 시 dangling <none> 이미지 누적 — 동일 태그 (myapp:dev) 로 새 빌드를 돌리면 이전 이미지가 untag 되어 dangling 으로 남음. 정상 메커니즘이지만 자동 정리가 없으면 디스크가 빠르게 찬다. CI 스크립트 종료 시 docker image prune -f 한 줄로 누적 차단. WSL2 백엔드는 sparse VHDX 라 docker prune 만으로는 호스트 디스크 회수 안 됨 — Optimize-VHD -Mode Full 또는 diskpart compact vdisk 까지 돌려야 실제 환원.
하고픈 말
Docker 는 컨테이너의 표준 도구이자 출발점입니다. 멀티스테이지 + BuildKit 캐시 마운트 + .dockerignore 셋이 함께 있을 때 빌드 시간 · 이미지 크기 · 재현 가능성 세 자리가 모두 좋아집니다. latest 태그를 피하고 명시적 버전 핀.
Next
- docker-compose-patterns
- caddy-not-nginx
Docker 공식 문서 · Dockerfile 레퍼런스 · BuildKit · OCI Image Spec · OCI Runtime Spec · Podman · Distroless 를 참고합니다.