dev.Log

ML Docker 이미지 크기 줄이는 법 본문

인공지능

ML Docker 이미지 크기 줄이는 법

초코푸딩 2026. 1. 2. 14:15

PyTorch/Transformers 이미지가 수 GB 되는 이유와 실전 다이어트 전략

ML 서비스(특히 PyTorch/Transformers/Whisper/LLM)를 Docker로 패키징하면 이미지가 쉽게 수 GB가 된다.
쿠버네티스 배포가 느려지고, 레지스트리 저장비가 늘고, CI 빌드 시간도 폭발한다.

이 글은 “이미지 크기가 커지는 원인”을 짚고, 실제로 효과가 큰 줄이는 방법을 우선순위대로 정리한다.


1. 왜 ML 이미지는 기본이 수 GB인가?

가장 흔한 원인은 다음 조합이다.

  • base 이미지가 큼: nvidia/cuda:*, pytorch/pytorch:*
  • 빌드 도구 포함: gcc, make, cmake, git
  • Python 휠이 GPU/BLAS 포함: torch, xformers, onnxruntime-gpu
  • 캐시가 남음: pip cache, apt lists, conda pkgs
  • 모델 파일을 이미지에 포함: *.pt, *.safetensors, *.onnx

즉, “학습/빌드 환경”과 “실행 환경”을 한 이미지에 섞으면 거의 무조건 커진다.


2. 가장 효과 좋은 6가지 전략 (우선순위)

전략 A) 멀티스테이지 빌드로 “빌드 도구” 제거

컴파일이 필요한 패키지(예: 일부 audio/lib, custom ops)가 있을 때 특히 효과가 크다.

  • 1단계(builder): gcc, cmake, git 포함해서 빌드
  • 2단계(runtime): 결과물(venv/site-packages)만 복사

핵심은 “런타임 이미지에 build-essential을 남기지 않는다”다.


전략 B) base 이미지를 목적에 맞게 최소화

대부분 아래 원칙이 먹힌다.

  • CPU 서비스: python:3.x-slim 또는 debian:bookworm-slim + python
  • GPU 추론: nvidia/cuda:<ver>-runtime-ubuntuXX.XX (devel 말고 runtime)
  • PyTorch GPU: 필요하면 pytorch/pytorch 대신 CUDA runtime 기반 + pip로 torch 설치

주의:

  • *-devel 이미지는 개발 헤더/컴파일러까지 포함해서 크기가 확 커진다.
  • “실행만” 하면 runtime이 정답이다.

전략 C) pip/apt 캐시를 “한 레이어에서” 없애기

Docker는 레이어 단위로 저장되므로, 설치와 삭제를 같은 RUN에서 해야 의미가 있다.

  • apt:
    • rm -rf /var/lib/apt/lists/*
  • pip:
    • pip install --no-cache-dir ...
  • conda:
    • conda clean -afy (하지만 운영에선 conda 자체를 피하는 게 더 큼)

전략 D) 모델 파일을 이미지에 넣지 말고 “런타임 다운로드/볼륨”으로 분리

이미지에 모델(수백 MB~수 GB)을 COPY하면 이미지가 끝없이 커지고, 배포/롤백이 느려진다.

권장:

  • 모델은 S3/MinIO/NFS/Artifact repo에서 내려받기
  • Kubernetes면 PVC로 마운트
  • 또는 initContainer에서 모델 다운로드 후 공유 볼륨 사용

모델이 자주 바뀌는 경우 특히 효과적이다.


전략 E) 의존성을 최소화하고 “불필요한 GPU 패키지”를 빼기

예를 들어 CPU만 쓰는데도 onnxruntime-gpu, cupy, tensorflow 같은 게 들어가면 크기가 폭발한다.

체크리스트:

  • torch가 CPU면 --index-url https://download.pytorch.org/whl/cpu 사용
  • CUDA가 필요 없으면 GPU 관련 휠 제거
  • transformers는 최소 extras만 사용(예: transformers[torch] 남발 금지)

전략 F) 최종 이미지에서 테스트/툴/소스 제거

실무에서 흔히 남는 것들:

  • tests/, .git/, docs/, 예제 데이터
  • 빌드 로그/캐시
  • 필요 없는 locale, tzdata 등

.dockerignore로 원천 차단하는 게 가장 확실하다.


3. CPU용 “슬림” 예시 Dockerfile (실전 템플릿)

핵심: slim + venv + no-cache + apt list cleanup

 
FROM python:3.11-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /app # 최소 OS deps만 (예: ffmpeg 필요하면 추가) RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates \ && rm -rf /var/lib/apt/lists/* # venv RUN python -m venv /venv ENV PATH="/venv/bin:$PATH" COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "main.py"]

이 형태로만 바꿔도 “불필요한 캐시” 때문에 커지던 이미지가 크게 줄어드는 경우가 많다.


4. GPU 추론용 “runtime-only” 예시 Dockerfile

핵심: nvidia/cuda:*runtime* + pip 캐시 제거 + 필요 라이브러리 최소화

 
FROM nvidia/cuda:12.1.1-runtime-ubuntu22.04 ENV DEBIAN_FRONTEND=noninteractive \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /app RUN apt-get update \ && apt-get install -y --no-install-recommends \ python3 python3-venv python3-pip \ ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN python3 -m venv /venv ENV PATH="/venv/bin:$PATH" COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "serve.py"]

주의:

  • torch GPU 휠은 CUDA 버전 매칭이 중요하다.
  • base CUDA 버전과 torch wheel의 CUDA 호환을 맞추지 않으면 런타임에서 import가 깨진다.

5. 이미지 크기를 실제로 줄였는지 확인하는 방법

(1) 전체 크기

 
docker images

(2) 레이어별로 뭐가 큰지

 
docker history --no-trunc <IMAGE>

여기서 큰 레이어가:

  • apt 설치
  • pip 설치
  • 모델 COPY
    인지 바로 보인다.

(3) 컨테이너 내부에서 큰 디렉토리 찾기

 
du -h -d 2 / | sort -h | tail

6. 자주 하는 실수

  • RUN apt-get update를 따로 하고 cleanup을 다음 레이어에서 함
    → 레이어에 apt list가 그대로 남는다.
  • pip 설치 시 캐시 남김
    → --no-cache-dir 필수
  • 모델을 이미지에 COPY
    → 모델 업데이트마다 이미지 재배포/캐시 무효화
  • devel 이미지를 런타임에 사용
    → 실행에 필요 없는 gcc/cmake까지 포함

결론: “빌드 환경”과 “실행 환경”을 분리하면 대부분 해결된다

ML Docker 이미지 다이어트의 핵심은 하나다.

  • 빌드 도구는 builder에만
  • 실행에는 runtime만
  • 캐시는 설치 단계에서 없애기
  • 모델은 이미지 밖으로

이 4가지만 지켜도 체감상 절반 이상 줄어드는 경우가 많다.

Comments