# Docker 이미지 최적화: 효율적인 빌드를 위한 모범 사례

발행: (2025년 12월 2일 오전 07:04 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

소개

Docker 이미지​는 컨테이너화된 애플리케이션의 기반입니다. 크고 비효율적인 이미지는 빌드 속도를 늦추고, 배포 시간을 늘리며, 저장소 사용량을 증가시킬 수 있습니다. 이미지를 최적화하면 더 빠른 배포, 향상된 성능 및 자원 소비 감소를 보장합니다.

큰 이미지와 비효율적인 이미지가 배포에 미치는 영향

무거운 이미지는 디스크 공간을 많이 차지하고 네트워크 전송 시간을 늘리며, 이는 CI/CD 파이프라인 및 클라우드 배포에서 매우 중요합니다. 효율적인 이미지는 작업을 더 민첩하게 만들고 운영 비용을 절감합니다.

1. 슬림 베이스 이미지 사용

최소 이미지 선택 (Alpine, Slim 변형)

가능하면 최소 또는 “slim” 베이스 이미지로 시작해 불필요한 패키지를 줄이세요. 예를 들어 python:3.10 대신 python:3.10-slim 또는 alpine을 고려합니다. 최소 이미지는 불필요한 패키지와 라이브러리를 제거해 이미지 크기를 줄이고 보안을 강화합니다.

불필요한 의존성 감소

애플리케이션에 꼭 필요한 패키지와 라이브러리만 설치하세요. 빌드 도구나 문서 파일을 런타임 이미지에 포함하지 않도록 합니다.

크기와 기능의 균형 맞추기

슬림 이미지는 작지만, 일부 애플리케이션은 특정 라이브러리를 필요로 할 수 있습니다. 필요한 기능을 제공하면서도 크기를 최소화할 수 있는 베이스 이미지를 선택해 런타임 오류를 방지하세요.

2. 멀티‑스테이지 빌드

멀티‑스테이지 빌드란?

멀티‑스테이지 빌드는 빌드 환경과 런타임 환경을 분리할 수 있게 해줍니다. 이 기법을 사용하면 빌드 단계에서 컴파일 도구를 포함하고, 최종 단계에서는 최종 아티팩트만 복사해 이미지 크기를 크게 줄일 수 있습니다.

빌드 환경과 런타임 환경 분리

Stage 1: 필요한 모든 의존성을 포함해 애플리케이션을 컴파일하거나 빌드합니다.
Stage 2: 최종 결과물만 더 작은 베이스 이미지에 복사하고, 빌드 도구와 중간 파일은 버립니다.

실전 예시 (Node.js + pnpm)

FROM node:22-alpine AS base

WORKDIR /app

COPY package*.json pnpm-lock.yaml* ./

RUN npm install -g pnpm \
    && pnpm install --frozen-lockfile

EXPOSE 3000

CMD ["pnpm", "run", "dev"]

Python Slim 멀티‑스테이지 예시

FROM python:3.12-slim

ENV PYTHONPATH=/app

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY alembic.ini .
COPY ./entrypoint.sh .
COPY . .

EXPOSE 8000

ENTRYPOINT ["./entrypoint.sh"]
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

3. Docker 레이어가 이미지 크기에 미치는 영향

Dockerfile의 각 명령(RUN, COPY, ADD)은 레이어를 생성합니다. 작은 레이어가 많이 쌓이면 전체 이미지 크기가 증가할 수 있습니다. 관련 명령을 하나의 RUN에 합쳐 레이어 수를 줄이세요:

RUN apt-get update && \
    apt-get install -y curl git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

캐시와 임시 파일은 같은 RUN 명령 안에서 삭제해야 합니다. 그렇지 않으면 이전 레이어에 남아 최종 이미지 크기를 키우게 됩니다.

4. .dockerignore 로 최적화

.dockerignore 파일은 빌드 컨텍스트에 포함되지 않아도 되는 파일을 제외합니다.

node_modules
.next
.tests
__pycache__
__pytest__
builds/
venv
logs

이렇게 하면 Docker에 전송되는 컨텍스트가 크게 줄어들어 빌드 속도가 빨라지고 불필요한 레이어가 생기지 않습니다.

5. 효율적인 캐시 활용

의존성 파일을 먼저 복사해 Docker 캐시를 최대한 활용하세요.

Node용

COPY package.json pnpm-lock.yaml ./
RUN pnpm install

Python용

COPY requirements.txt .
RUN pip install -r requirements.txt

의존성 파일이 변경되지 않는 한, 해당 단계는 캐시가 재사용되어 재처리 시간이 절감됩니다.

6. 일반적인 모범 사례

  • DOCKER_TAG=1.0.0 또는 IMAGE_VERSION=1.0.0 같은 태그를 사용해 버전을 추적하고 빌드 간 혼동을 방지합니다.
  • docker image ls 로 정기적으로 이미지 목록을 검토하고 오래된 이미지를 삭제합니다.
  • CI/CD 파이프라인에 최적화 단계를 통합해 일관되고 작으며 빠른 빌드를 보장합니다.
  • 프로덕션 이미지에 테스트 도구와 문서 파일을 포함하지 않도록 합니다.
  • 가능한 한 최소 이미지 사용을 우선시합니다.

결론

이러한 모범 사례를 적용하면 애플리케이션 성능이 향상되고 운영 비용이 감소하며, 현대적이고 확장 가능한 환경에 적합한 작고 효율적인 이미지를 만들 수 있습니다. 멀티‑스테이지 빌드, 슬림 이미지 사용, 레이어 정리 및 .dockerignore는 고성능·유지보수가 쉬운 이미지를 만드는 핵심 요소입니다.

Back to Blog

관련 글

더 보기 »

AWS와 Docker에서 Jenkins

Jenkins on AWS + Docker용 표지 이미지 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-upload...