숏컷 코드
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["npm", "start"]문법
어떤 Dockerfile 지시어를 먼저 떠올리면 되나
| 상황 | 먼저 떠올릴 선택 |
|---|---|
| 베이스 이미지 선택 | FROM |
| 작업 디렉터리 고정 | WORKDIR |
| 파일 복사 | COPY |
| 빌드 시 명령 실행 | RUN |
| 컨테이너 기본 시작 명령 | CMD |
| 고정 진입점 지정 | ENTRYPOINT |
FROM — 베이스 이미지 선택이 이미지 크기와 보안의 시작점이다
FROM은 새 이미지의 기반이 될 베이스 이미지를 지정합니다. alpine 계열은 수 MB 수준으로 가볍지만 musl libc를 씁니다. slim은 불필요한 패키지를 제거한 Debian 기반입니다. 전체 이미지(예: node:22)는 편리하지만 수백 MB에 달합니다. 운영용 이미지는 alpine이나 slim을 기반으로 시작해 크기와 공격 면적을 줄이는 것이 기본 전략입니다.
FROM node:22-alpine # 경량, 운영용 권장
FROM node:22-slim # Debian 기반, 호환성 좋음
FROM node:22 # 전체 이미지, 개발 편의용RUN vs CMD vs ENTRYPOINT — 빌드 시점과 런타임 시점을 구분한다
RUN은 이미지 빌드 중에 실행되는 명령입니다. npm ci, pip install, 패키지 설치처럼 이미지를 만드는 과정에 필요한 작업에 씁니다. CMD는 컨테이너가 시작될 때 기본으로 실행할 명령을 지정하며, docker run에서 다른 명령을 붙이면 덮어씌워집니다. ENTRYPOINT는 덮어씌워지지 않는 고정 실행 명령이며, CMD를 기본 인자로 받는 패턴으로 함께 씁니다.
# 빌드 시 의존성 설치
RUN npm ci
# 컨테이너 시작 시 기본 명령 (docker run으로 덮어씌울 수 있음)
CMD ["npm", "start"]
# ENTRYPOINT + CMD 조합 — 항상 node를 실행하되 인자만 교체 가능
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run my-app worker.js → node worker.js로 실행됨COPY와 WORKDIR — 파일 위치와 작업 디렉터리를 명확히 해야 레이어 캐시가 효율적이다
WORKDIR은 이후 모든 지시어(COPY, RUN, CMD)의 기본 작업 디렉터리를 설정합니다. 별도 지정 없이 루트(/)에 파일을 쌓으면 관리가 어려워집니다. COPY는 빌드 컨텍스트의 파일을 이미지로 복사하며, 복사 순서가 레이어 캐시 효율에 직접 영향을 줍니다. 자주 바뀌는 소스 코드는 나중에 복사해야 의존성 설치 캐시가 유지됩니다.
WORKDIR /app
# 의존성 파일 먼저 복사 (소스 변경이 캐시에 영향 없음)
COPY package.json package-lock.json ./
RUN npm ci
# 소스는 나중에 복사
COPY src/ ./src/
COPY tsconfig.json ./RUN, CMD, ENTRYPOINT는 빌드 시점과 실행 시점을 나눠서 봐야 한다
RUN은 이미지를 만드는 동안 실행되고, CMD와 ENTRYPOINT는 컨테이너가 시작될 때 영향을 줍니다. 설치 명령을 CMD에 넣으면 컨테이너가 켜질 때마다 다시 설치를 시도하게 되고, 기본 실행 명령을 RUN에 넣으면 빌드 중 한 번만 실행되고 끝납니다. 이 구분을 먼저 잡아야 Dockerfile이 자연스럽게 읽힙니다.
# 빌드 시점
RUN npm ci
# 런타임 시점
CMD ["npm", "start"]체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 경량 운영 이미지가 필요할 때 | FROM alpine 또는 slim 기반 |
| 빌드 중 패키지 설치 | RUN |
| 컨테이너 기본 실행 명령 | CMD |
| 덮어씌울 수 없는 고정 진입점 | ENTRYPOINT |
| 의존성 캐시를 유지하며 소스만 교체 | COPY 순서 조정 (의존성 파일 먼저) |
주의할 점
Dockerfile은 단순 셸 스크립트가 아니라 레이어 구조를 가진 빌드 정의다. RUN 명령 하나가 레이어 하나를 만들고, 중간 레이어의 파일이 최종 이미지에 포함되므로 비밀 파일을 RUN으로 복사하고 나중에 삭제해도 이미지에서 추출할 수 있다. 민감 파일은 처음부터 빌드 컨텍스트에 포함시키지 않거나 BuildKit secret을 사용해야 한다.
# 잘못된 패턴
COPY . .
CMD ["npm", "ci"]
# 컨테이너가 시작될 때마다 의존성을 다시 설치하게 됨참고 링크
2 sources