문득 내가 이용하는 도커 이미지들의 사이즈가 엄청 작다는 것을 알게 되었다. 내가 빌드한 것은 GB 단위여서 당연히 그게 정상인 줄 알았는데 애용한던 filebrowser/filebrowser
는 30.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
로 사이즈를 줄일 수 있게 되었다.
Ghost