파이썬 도커 이미지 최적화: 크기 43–57% 줄이기
멀티스테이지 빌드와 파이썬 슬림 이미지를 사용하면 런타임 이미지 크기를 895 MB에서 508 MB로 줄일 수 있습니다(-43%). 코드 변경 후 빌드 시간은 56초에서 16초로 단축됩니다. 이는 쿠버네티스 배포 속도를 높이고, 저장 공간을 절약하며, 트래픽을 줄입니다.
최적화는 트래픽 급증 시 빠른 팟 스케일링과 사용자 지연 시간 감소 같은 핵심 문제를 해결합니다. 의존성은 Poetry로 관리되며, 테스트는 빌더 스테이지에서 실행됩니다.
.dockerignore와 슬림 이미지
.dockerignore를 통해 테스트와 불필요한 파일을 제외합니다. 테스트는 빌드 스테이지에서만 필요합니다.
python:3.13-slim-bookworm으로 전환하세요. 전체 이미지는 수백 MB를 추가합니다.
플래그로 pip/Poetry 캐시를 비활성화합니다:
- pip:
--no-cache-dir - Poetry:
poetry cache clear --all pypi
멀티스테이지 빌드: Dockerfile 분석
빌더 스테이지는 Poetry, 의존성을 설치하고 pytest를 실행합니다. 런타임 스테이지는 site-packages, 바이너리(gunicorn, uvicorn), 코드만 복사합니다.
# 빌더 스테이지
FROM python:3.13-slim-bookworm AS builder
ENV PYTHONUNBUFFERED=1 \
LANG=C.UTF-8 \
PYTHONDONTWRITEBYTECODE=1
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
curl \
gcc \
libc-dev \
&& pip install --no-cache-dir 'poetry==2.3.2' \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /code
COPY pyproject.toml poetry.lock* ./
RUN poetry config virtualenvs.create false \
&& poetry install --no-root --no-dev --no-interaction --no-ansi \
&& poetry cache clear --all pypi --no-interaction || true \
&& rm -rf ~/.cache/pip
COPY . .
RUN pytest
# 런타임 스테이지
FROM python:3.13-slim-bookworm
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
LANG=C.UTF-8
WORKDIR /code
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin/gunicorn /usr/local/bin/gunicorn
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=builder /code /code
기본 최적화 결과:
| 지표 | 이전 | 이후 | 변화 |
|---------|------|-------|-----------|
| 이미지 크기, MB | 894.84 | 508 | -43% |
| 전체 빌드 시간, s | 58 | 315 | +443% |
| 편집 후 빌드 시간, s | 56 | 16 | -71% |
첫 빌드는 빌더 레이어로 인해 느리지만, 캐싱이 반복 작업을 가속화합니다.
고급 방법: Chainguard와 수동 분석
Chainguard 이미지
Chainguard는 셸, apt/apk를 제외하여 공격 표면을 최소화합니다. 기본 이미지에 CVE가 없습니다. 절감 효과: 50–150 MB.
단점:
- 셸 없이 디버깅
- 최신 태그만 무료
- 유료 버전은 비쌈
고보안 프로젝트에 적합합니다.
dive를 이용한 수동 분석
레이어 분석:
docker history --format "{{.CreatedBy}}: {{.Size}}" image:tag
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest image:tag
큰 런타임 레이어에 집중하세요. 디렉토리 접기(Shift+Space), 불필요한 라이브러리 제거. 리눅스 전문 지식 필요, 드물게 효과적입니다.
극단적 최적화: scratch
scratch에서 런타임—필요한 libc만 복사. 크기가 384 MB로 감소합니다(원본 대비 -57%, 멀티스테이지 대비 -24%).
단점:
- 디버깅 불가능
- 새 의존성은 수동 라이브러리 추가 필요
- 디버깅 시간: 1시간 이상
수천 개의 팟, 서버리스(Knative, Fargate)에 적합합니다. Go보다 파이썬에서 더 어렵습니다.
크기 비교:
- 멀티스테이지 없음: 894 → 384 MB (-57%)
- 멀티스테이지: 508 → 384 MB (-24%)
빌드 시간 최적화
코드 전에 pyproject.toml/poetry.lock 복사:
- COPY pyproject.toml poetry.lock* ./
- RUN poetry install
- COPY . .
- RUN pytest
코드 변경 시 의존성 캐시가 유지됩니다. 가속화: 58 → 14 s (x4).
핵심 요약
- 멀티스테이지 + 슬림: 크기 -43%, 반복 시간 -71%.
- .dockerignore + no-cache: 런타임에서 테스트와 캐시 제외.
- COPY 순서: 의존성을 코드와 별도로 캐싱.
- Scratch: -57%, 극단적 경우(수천 팟)에만.
- Chainguard/dive: 보안과 세부 조정용.
— Editorial Team
아직 댓글이 없습니다.