← 전체 글로 돌아가기

Docker

.dockerignore 없이 빌드하면 이미지가 왜 커지는가

.dockerignore를 설정하지 않으면 node_modules나 .git 같은 폴더가 통째로 이미지에 포함된다. 이미지 크기와 빌드 시간, 보안 모두 영향을 받는다.

Dockerfile을 처음 만들 때 .dockerignore를 빠뜨리는 경우가 많다. COPY . . 한 줄이면 소스 코드가 다 들어간다고 생각하기 쉬운데, 실제로는 프로젝트 루트에 있는 모든 것이 빌드 컨텍스트로 넘어간다.

무엇이 들어가는지 확인한다

빌드 컨텍스트에 무엇이 포함되는지 보려면 빌드 시 출력 첫 줄을 확인하면 된다.

Sending build context to Docker daemon  512.4MB

이 숫자가 크다면 불필요한 파일이 들어가고 있는 것이다. node_modules(수백 MB), .git 디렉토리(커밋 히스토리 전체), .env 파일, 빌드 결과물인 .next 폴더까지 전부 데몬으로 전송된 다음 이미지 레이어에 쌓인다.

.dockerignore 기본 작성법

Node.js 프로젝트를 기준으로 최소한 이것은 제외해야 한다.

# 의존성 (컨테이너 안에서 npm ci로 설치)
node_modules
npm-debug.log

# 버전 관리
.git
.gitignore

# 빌드 캐시/결과물
.next
dist
build

# 환경 변수 (절대 이미지에 포함시키지 않는다)
.env
.env.local
.env.*.local

# 에디터/OS
.DS_Store
.idea
.vscode

.env가 이미지에 포함되면 docker history 명령이나 레이어 추출으로 내용을 확인할 수 있다. 이미지를 레지스트리에 올리는 순간 보안 사고로 이어질 수 있다.

node_modules 제외가 핵심

node_modules를 제외하지 않으면 두 가지 문제가 생긴다. 첫째, 수백 MB를 매 빌드마다 전송한다. 둘째, 컨테이너 안 OS(보통 Alpine이나 Debian)와 다른 플랫폼용 바이너리가 섞일 수 있다. 예를 들어 macOS에서 npm installnode_modules를 Linux 컨테이너에 복사하면 네이티브 모듈이 동작하지 않는다.

Dockerfile에서 npm ci를 실행하는 이유가 여기 있다.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build

이미지 크기 비교

.dockerignore 없이 빌드한 이미지와 있을 때를 비교하면 차이가 바로 보인다.

docker image ls | grep my-app
# my-app  without-ignore  1.2GB
# my-app  with-ignore     180MB

크기가 줄면 레지스트리 푸시·풀 시간이 줄고, 컨테이너 시작 속도도 조금 빨라진다. .dockerignore는 Dockerfile과 같은 디렉토리에 두면 자동으로 적용된다.