Docker 빌드 시간을 30초에서 2초로 단축
출처: Dev.to
코드를 한 줄만 바꿔도 Docker 빌드가 30초 이상 걸린다면, Dockerfile이 오히려 방해하고 있는 겁니다. 번개 같은 빌드 속도의 비결은 레이어 캐싱을 제대로 활용하는 데 있습니다.
다음은 Dockerfile을 최적화해 최대 성능과 예측 가능성을 확보하기 위한 다섯 가지 핵심 규칙입니다.
Docker가 이미지를 빌드할 때, 각 명령을 레이어로 캐시하고 해당 레이어의 내용 해시가 변하지 않으면 재사용합니다. 하지만 하나의 레이어가 바뀌면 그 이후의 모든 레이어가 다시 빌드됩니다.
이러한 연쇄 효과 때문에, 변경 가능성이 낮은(드물게 바뀌는) 명령을 먼저, 변동성이 높은(자주 바뀌는) 명령을 나중에 배치해야 합니다.
개발자들이 가장 흔히 저지르는 실수는 모든 파일을 한 번에 복사하는 것인데, 이 경우 매 커밋마다 캐시가 무효화되고 의존성까지 다시 설치하게 됩니다. 대신 COPY 단계를 나눠서 처리하세요:
- 의존성 메타데이터가 들어 있는 매니페스트 파일만 먼저 복사합니다(예:
pyproject.toml,package.json). - 패키지 매니저 설치 명령을 실행합니다(예:
pip install). - 실제 코드 파일을 마지막에 복사합니다.
코드 파일은 개발 중에 자주 바뀌므로 가장 마지막에 두면 무거운 의존성 설치 레이어가 캐시된 상태로 유지됩니다.
1. 의존성 매니페스트만 복사
COPY pyproject.toml uv.lock ./
2. 의존성 설치 (캐시 활용!)
RUN pip install --no-cache-dir fastapi uvicorn[standard]
3. 애플리케이션 코드 복사 (변동성)
COPY . .
.dockerignore
.dockerignore 파일이 없으면 대용량이거나 민감한 디렉터리가 Docker 빌드 컨텍스트에 포함될 위험이 있습니다.
.git, .env, .venv, node_modules와 같은 디렉터리는 반드시 제외하세요. 이들 중 일부는 빌드를 느리게 만드는 불필요한 데이터가 많고, .env와 같이 비밀 정보를 포함한 경우 이미지에 절대 포함돼서는 안 됩니다.
레이어 최적화
각 RUN 명령은 읽기 전용 레이어를 하나씩 생성합니다. 업데이트, 패키지 설치, 캐시 정리를 세 개의 별도 RUN 명령으로 나누면, 정리 작업은 해당 레이어에서만 파일을 삭제하고 이전 레이어는 여전히 부피가 큰 상태로 남게 됩니다.
이미지를 작게 유지하려면 명령을 하나로 연결하고 같은 단계에서 정리 작업을 수행하세요:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -fr /var/lib/apt/lists/*
태그 사용 시 주의
python:latest나 node:latest와 같은 일반 태그에 의존하지 마세요.
latest 태그는 계속 변하는 목표이므로, 기반 OS나 언어 버전이 예기치 않게 업데이트될 경우 빌드의 재현성과 예측 가능성을 조용히 깨뜨릴 수 있습니다. 항상 특정하고 불변하는 버전을 고정하세요(예: python:3.12.7-slim-bookworm). 이렇게 하면 배포가 견고해집니다.