Docker 컨테이너 최적화 - 이미지 크기 줄이기



Docker 이미지 크기를 줄이면 빌드 시간 단축, 배포 속도 향상, 스토리지 비용 절감 효과가 있습니다.



언제 필요한가요?



  • 이미지 크기가 1GB 이상으로 커질 때

  • CI/CD 파이프라인 속도 개선

  • 컨테이너 시작 시간 단축

  • 네트워크 대역폭 절약



1. 경량 베이스 이미지 사용


# 안 좋은 예 - 불필요한 패키지 포함
FROM ubuntu:20.04 # ~72MB
FROM node:18 # ~1GB

# 좋은 예 - 경량 이미지
FROM alpine:3.18 # ~5MB
FROM node:18-alpine # ~172MB
FROM openjdk:17-alpine
FROM python:3.11-slim


2. 멀티스테이지 빌드


# Java 예시
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

FROM openjdk:17-jre-alpine
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

# Node.js 예시
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html


3. 레이어 최적화


# 안 좋은 예 - 레이어 많음
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN apt-get clean

# 좋은 예 - 레이어 합치기
RUN apt-get update &&
apt-get install -y --no-install-recommends
curl
wget &&
apt-get clean &&
rm -rf /var/lib/apt/lists/*


4. .dockerignore 활용


# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
*.md
Dockerfile
.dockerignore
.env
.env.*
coverage
test
__tests__
*.test.js
.idea
.vscode


5. 불필요한 파일 제거


# 빌드 후 캐시 정리
RUN npm ci && npm cache clean --force

# apt 캐시 정리
RUN apt-get update &&
apt-get install -y package &&
rm -rf /var/lib/apt/lists/*

# pip 캐시 정리
RUN pip install --no-cache-dir -r requirements.txt


6. COPY 순서 최적화


# 자주 변경되지 않는 것 먼저
COPY package*.json ./
RUN npm install

# 자주 변경되는 소스코드는 나중에
COPY . .
RUN npm run build

# 이렇게 하면 package.json이 변경되지 않으면
# npm install 레이어는 캐시됨


7. 실행에 필요한 것만 포함


# Java: JDK 대신 JRE
FROM openjdk:17-jdk-alpine # 빌드용
FROM openjdk:17-jre-alpine # 실행용 (더 작음)

# distroless 이미지 (쉘도 없는 최소 이미지)
FROM gcr.io/distroless/java17


실전 Dockerfile 예시



Spring Boot


FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY gradle ./gradle
COPY gradlew build.gradle settings.gradle ./
RUN ./gradlew dependencies
COPY src ./src
RUN ./gradlew bootJar

FROM eclipse-temurin:17-jre-alpine
RUN addgroup -S app && adduser -S app -G app
USER app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]


Node.js


FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -S app && adduser -S app -G app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER app
EXPOSE 3000
CMD ["node", "dist/index.js"]


이미지 크기 확인


# 이미지 크기 확인
docker images

# 레이어별 크기 분석
docker history 이미지명

# dive 도구 사용 (상세 분석)
dive 이미지명


크기 비교 예시








방법크기
기본 (ubuntu + jdk)~800MB
alpine + jre~200MB
멀티스테이지 + alpine~150MB
distroless~100MB


추가 팁



  • scratch 이미지: Go 같은 정적 바이너리용 최소 이미지

  • 빌드 시 --squash 옵션으로 레이어 합치기 (실험적)

  • docker-slim 도구로 자동 최적화