← 전체 글로 돌아가기

Docker

Docker 이미지 용량이 너무 크면 배포가 느려진다

같은 애플리케이션인데 배포 속도가 느릴 때 이미지 레이어를 최적화하는 방법.

Docker 이미지가 크면 배포 시간, 스토리지, 네트워크 대역폭이 모두 낭비된다. 로컬에서는 문제 없지만 배포할 때마다 몇 분이 걸리면, 이미지 용량부터 확인해야 한다.

현재 상태 파악

# 이미지 크기 확인
docker images | grep myapp

# 레이어별 용량 확인
docker history myapp:latest --no-trunc

각 레이어의 크기를 보면, 어느 단계에서 용량이 늘었는지 알 수 있다.

컨테이너 상태 확인

# 실행 중인 컨테이너의 디스크 사용량
docker exec myapp-container du -sh /app/
docker exec myapp-container du -sh /

불필요한 파일이 이미지에 포함되어 있지 않은가?

Dockerfile 최적화

1. Multi-stage build

빌드 단계와 실행 단계를 분리한다.

# ❌ 비효율: 모든 빌드 도구가 이미지에 남음
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]

# ✅ 효율: 빌드 도구는 버리고 결과만 복사
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build

FROM node:18-alpine  # 작은 베이스 이미지
WORKDIR /app
COPY --from=builder /app/dist /app/dist
COPY --from=builder /app/node_modules /app/node_modules
COPY package.json .
CMD ["npm", "start"]

alpha -> alpine으로 바꾸면 베이스 이미지 자체도 훨씬 작다.

2. 불필요한 파일 제외

# .dockerignore 파일
node_modules/
npm-debug.log
.git/
.vscode/
TESTS/
*.md

.git 디렉토리만 제외해도 수십 MB가 줄어든다.

3. 캐시 활용

# ❌ 비효율: 코드 변경 시마다 의존성을 다시 설치
COPY . .
RUN npm install

# ✅ 효율: 의존성은 캐시하고, 코드 변경만 다시 빌드
COPY package.json package-lock.json ./
RUN npm ci  # npm install 대신 npm ci 사용 (더 안정적)
COPY . .
RUN npm run build

package.json 변경까지만 캐시되고, 코드 변경은 빠르게 다시 빌드된다.

4. 베이스 이미지 선택

# 크기 비교 (MB)
# ubuntu:latest        → ~77 MB
# node:18              → ~900 MB
# node:18-alpine       → ~170 MB
# node:18-slim         → ~160 MB

FROM node:18-alpine

alipne이나 slim을 쓰면 수백 MB 절약할 수 있다.

빌드 최적화

# 빌드 시 불필요한 것 제거
RUN npm install --production  # dev 의존성 제외
RUN npm run build
RUN rm -rf /app/src /app/test /app/*.json  # 소스 코드 제거

컴파일된 코드만 배포하면 된다면, 소스 코드는 제거해도 된다.

환경변수와 비교 기준

배포 환경과 로컬 빌드의 차이가 있을 수 있다.

# Docker Hub에서 이미지 크기 확인
docker pull myapp:latest
docker images | grep myapp

# 레지스트리의 메타데이터도 확인
skopeo inspect docker://myapp:latest

로컬 이미지보다 레지스트리의 이미지가 더 클 수 있다.

확인 결과와 그 의미

로컬 빌드: 500 MB
레지스트리: 500 MB  → 일치하면 정상

로컬 빌드: 500 MB
레지스트리: 1 GB    → 문제 있음

レジストリ에서 더 크면, 빌드 서버의 Dockerfile이 다를 가능성이 있다.

배포 후 확인

이미지 최적화 후에도 실행 시간을 확인한다.

# 컨테이너 시작 시간
time docker run myapp:latest

# 배포된 컨테이너 상태
docker logs <container-id> | head -10  # 시작 로그

이미지 크기와 시작 속도가 모두 개선됐는가?

최적화 체크리스트

  1. 현재 이미지 크기 확인
  2. docker history로 레이어별 용량 파악
  3. Multi-stage build 도입
  4. .dockerignore 파일 작성
  5. 베이스 이미지를 alpine/slim으로 변경
  6. npm ci 사용, 캐시 활용
  7. 불필요한 파일 제거 (소스, 테스트 등)
  8. 로컬과 배포 환경의 빌드 결과 비교

Docker 이미지 최적화는 한 번 하면 매번 배포할 때마다 시간이 절약된다. 작은 개선들이 모이면 큰 효과가 난다.