홈으로 돌아가기

Python Docker 최적화: -43-57% 크기

기사가 Python Docker 이미지 최적화를 분해합니다: multi-stage build로 크기 43% 감소, scratch로 57%. Dockerfile 예제, 벤치마크, dive 분석. 중급/시니어 개발자에게 적합.

Python Docker: scratch와 multi-stage로 크기 -57%
Advertisement 728x90

파이썬 도커 이미지 최적화: 크기 43–57% 줄이기

멀티스테이지 빌드와 파이썬 슬림 이미지를 사용하면 런타임 이미지 크기를 895 MB에서 508 MB로 줄일 수 있습니다(-43%). 코드 변경 후 빌드 시간은 56초에서 16초로 단축됩니다. 이는 쿠버네티스 배포 속도를 높이고, 저장 공간을 절약하며, 트래픽을 줄입니다.

최적화는 트래픽 급증 시 빠른 팟 스케일링과 사용자 지연 시간 감소 같은 핵심 문제를 해결합니다. 의존성은 Poetry로 관리되며, 테스트는 빌더 스테이지에서 실행됩니다.

.dockerignore와 슬림 이미지

.dockerignore를 통해 테스트와 불필요한 파일을 제외합니다. 테스트는 빌드 스테이지에서만 필요합니다.

Google AdInline article slot

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), 코드만 복사합니다.

Google AdInline article slot
# 빌더 스테이지
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

기본 최적화 결과:

| 지표 | 이전 | 이후 | 변화 |

|---------|------|-------|-----------|

Google AdInline article slot

| 이미지 크기, 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

Advertisement 728x90

다음 읽기