Docker 이미지 사이즈 최적화

Docker 이미지 사이즈 최적화

문득 내가 이용하는 도커 이미지들의 사이즈가 엄청 작다는 것을 알게 되었다. 내가 빌드한 것은 GB 단위여서 당연히 그게 정상인 줄 알았는데 애용한던 filebrowser/filebrowser30.6MB밖에 되지 않았다. 그래서 이번에 이미지 사이즈를 최적화 하는 방법에 대해서 알아 보았다.

https://github.com/baealex/sd-prompt-palette

시험삼아 이미지 사이즈를 최적화해 볼 이미지는 위 프로젝트다.

docker build -t sdpp-test .

이 프로젝트의 이미지는 현재 1.44GB 정도에 육박한다 💦


이미지 분석

오픈소스로 만들어진 dive라는 CLI 도구가 있는데 이를 활용하면 Dockerfile에서 각 레이어가 어느 정도의 용량을 차지하는지, 이미지 내부에서 어디에 위치하고 있는지 파악할 수 있다. 대략 아래와 같은 비주얼이다.

dive를 이용해서 사이즈 파악해보자

dive sdpp-test

WORKDIR /app

위 라인을 기점으로 위 쪽은 베이스 이미지가 차지하는 용량 아래는 내가 추가한 용량으로 볼 수 있다.


이미지 최적화

1. 작은 베이스 이미지 사용

우선 베이스 이미지가 차지하는 용량이 1GB 정도로 비교적 크다는 것을 알 수 있다. 여기서는 node:21 이미지를 사용하고 있다. 기본 이미지의 경우 Debian 계열을 바탕으로 빌드되어 있는데 다른 계열을 바탕으로 만들어진 이미지도 제공하고 있다.

  • node:21 : 가장 기본이 Debian 기반으로 빌드된 이미지다.
  • node:21-slim : 더 경량화 된 Debian을 바탕으로 빌드된 이미지다.
  • node:21-alpine : 초경량 리눅스 배포판 Alpine Linux를 바탕으로 빌드된 이미지다.

여기서는 alpine으로 이미지를 바꿔주었고 크기는 474MB로 획기적으로 줄어들었다.

베이스 이미지가 140MB 정도만 차지하게 되었다.

# as-is
FROM node:21

# to-be
FROM node:21-alpine
2. dockerignore

이미지에는 꼭 필요한 파일만 담아야 한다. .gitignore와 유사한 신택스를 사용하는 .dockerignore 파일을 추가해서 빌드나 실행에 필요하지 않은 파일을 명시해 주는게 좋다.

# .md 확장자인 파일을 모두 무시 ex) README.md
*.md

# 빌드 및 실행을 위해 사용하는 특정 .md 파일은 포함 (아래는 예시)
!*.spec.md

# 디렉토리의 하위 디렉토리나 파일을 무시
.git/
logs/
node_modules/
3. 멀티 스테이지 빌드

이 과정도 불필요한 파일을 이미지에 포함하지 않는 방법에 해당한다.

현재 최적화를 진행하는 프로젝트에서는 웹 서버와 클라이언트가 모두 포함되어 있다. 이미지 내에서 클라이언트를 빌드하고 있으므로 이미지에는 서버 실행을 위한 패키지와 클라이언트 빌드를 위한 패키지를 모두 담고 있는 형태를 취하고 있다.

하지만 클라이언트의 경우에는 빌드된 파일만 제공되면 되므로 클라이언트 패키지와 빌드를 위해서 사용하는 소스 코드가 이미지에 포함되는 것은 불필요하다고 볼 수 있다.

server
   ├──node_modules # 필요
   ├──src # 필요
   └──client
         ├──node_modules # 불필요
         ├──src # 불필요
         └──dist # 필요

Dockerfile에서 빌드 stage를 분리하고 각 stage에서 필요한 파일만 가져올 수 있도록 할 수 있다.

# client라는 이름으로 stage 설정
FROM node:21-alpine as client

WORKDIR /app

COPY ./src/client/package.json ./
COPY ./src/client/pnpm-lock.yaml ./

RUN npx pnpm i

COPY ./src/client/ ./

RUN npm run build

...

FROM node:21-alpine

WORKDIR /app

# client stage에서 파일 복사
COPY --from=client /app/dist ./client/dist

위와같이 client stage에서 빌드한 결과물만 실제 이미지에 포함시킬 수 있다. 최종적으로 322MB로 사이즈를 줄일 수 있게 되었다.

이 글이 도움이 되었나요?

신고하기
0분 전
작성된 댓글이 없습니다. 첫 댓글을 달아보세요!
    댓글을 작성하려면 로그인이 필요합니다.