업무를 진행하며, 다양한 서버와 인프라를 도커 환경으로 묶어 봤다.
이 때, 어떨 때는 도커 빌드 속도가 빨랐다가 어느 때는 느리고, 이런저런 문제를 겪기도 했다.
dockerfile을 작성할 때 유의해야 할 세 가지를 뽑아 정리해 보았다.
1. 레이어 개수에 유의하기
Dockerfile의 각 명령어는, 대부분 새로운 레이어를 생성한다.
불필요하게 많은 레이어는 빌드 시간과 이미지 크기를 증가시켜, 효율성을 저하시킬 수 있다.
기존에는 가독성을 위해 다음과 같이 작성했었다.
FROM alpine:latest
RUN apk update
RUN apk add rust
RUN apk add cargo
...
하지만 위 dockerfile의 경우 벌써 네개의 레이어가 만들어진다.
따라서, 아래처럼 개선할 수 있다.
FROM alpine:latest
RUN apk update && apk add rust cargo
2. 레이어 캐싱 효율적으로 사용하기
docker는 빌드 과정에서 레이어를 캐싱하고 재사용함으로서 빌드 시간을 절약할 수 있다.
하지만, 아래처럼 생각 없이 dockerfile을 작성했다가는,
캐싱 없이 항상 모든 레이어를 재빌드하게 될 수도 있다.
FROM alpine:latest
COPY . /app
RUN apk update && RUN apk add python3 cargo
...
이 경우, COPY 명령어를 통해 복사되는 파일들이 변경되면,
이후의 모든 레이어는 캐시를 믿을 수 없게 된다.
위 경우, 종속성 및 빌드 도구 패키지의 설치가 끝난 다음,
실제 컨텐츠의 docker 복사가 이루어져도 되는 상황이기에,
다음과 같이 개선할 수 있다.
FROM alpine:latest
RUN apk update && apk add python3 cargo
COPY . /app
...
이 상황에서는, RUN 명령어 구문은 빌드 시에 항상 재사용되게 됨으로서,
쌓이게 되면 많은 자원을 아낄 수 있게 된다.
3. 레이어 크기 관리하기 : 멀티 스테이징
도커에 조금 익숙해졌을 무렵,
내가 만든 도커 이미지의 크기가 1GB가 넘어가는 것을 보고,
이대로는 안되겠다 싶어 개선해보려 다음과 같이 작성했었다.
FROM alpine:latest
RUN apk update && apk add rust cargo ...
COPY . /app
RUN cargo build ...
RUN apk del rust cargo && rm -rf /app/src ...
...
이렇게 작성하면, 빌드때에만 필요했던 패키지가 정리되기에,
도커 이미지 크기도 그만큼 줄어들어 도움이 될 줄만 알았다.
하지만, docker의 각 레이어는, 명령어에 따른 '변경 사항'을 기록한다.
따라서, 한번 생성된 레이어들의 크기는 변하지 않고,
저 RUN apk del은 패키지를 지운다는 데이터 레이어를,
오히려 추가만 할 뿐이었다.
멀티 스테이지 빌드
위 문제를 해결하기 위해 찾아보았고,
멀티 스테이지 빌드를 통해 깔끔히 해결할 수 있었다.
# 빌드 스테이지
FROM alpine as build-stage
RUN apk update && apk add rust cargo
COPY . /app
RUN cargo build ...
# 최종 이미지
FROM alpine
COPY --from=build-stage /app /app
위처럼 빌드 이미지를 통해 얻어진 '결과 패키지'만,
깨끗한 base 이미지로 가져오고,
필요 시 동작에 필요한 패키지만 추가함으로서,
이미지 크기를 획기적으로 줄일 수 있다.
또한, 빌드를 위해 복사된 소스 코드나 빌드 리소스들은,
빌드 이미지에만 남고 최종 이미지에는 빠지게 된다!
dockerfile을 작성할 때 얼마나 신경쓰냐에 따라,
이후 수많이 빌드를 할 때 누적되면 큰 차이가 된다!
'연구한 이야기 > 문제 해결 이야기' 카테고리의 다른 글
mysql connect 시에 timezone 관련해서 에러가 나요! (2) | 2024.03.02 |
---|---|
Android Studio NDK breakpoint가 잡히지 않아요! (0) | 2024.03.02 |
jenkins(image) 에서 docker buildx를 사용하고 싶어요! (0) | 2023.12.22 |
CMake 와 static library에서의 종속성 관리 (0) | 2023.12.16 |
서버 스트레스테스트 시 일정 주기로 멈춰요! (0) | 2023.12.09 |