docker multistage

# dockerfile 에서 
# RUN, ADD, COPY 명령마다 layer 가 생성된다. 기존의 이미지에서 이 명령들 중 수정되면 수정되는 곳 부터 새로운 layer 가 생성된다.
# CMD, LABEL, ENV, EXPOSE 임시 layer 로 생성되지만 실제 도커이미지에는 저장되지 않는다.

# layer 개수와 해시값(sha256)은 다음 명령으로 확인할 수 있다.
docker image inspect nginx:latest  | jq '.[0].RootFS'

# 최적화된 도커 이미지 생성하기
# 베이스가 될 이미지 사이즈가 작은것을 선택한다.
# alpine linux 는 유닉스 기본 명령어가 포함된 busybox(https://www.busybox.net/) 와 musl(https://musl.libc.org/) C 라이브러리만 포함하고 있어 사이즈가 아주 작다.
# 다만 python 을 사용한다면 apline 기반에서는 패키지 철치, 빌드 시간, 기타 취약점등 단점이 많기 때문에 debian(https://www.debian.org/releases/) 10(buster)나 11(bullseye) 을 사용하는것이 좋다.

# RUN 하나로 layer 개수를 줄이자.
# 다음의 경우 RUN 마다 layer 가 생성되지만 
RUN apt-get update
RUN apt-get install -y gcc
RUN apt-get install -y git

# 다음과 같이 하나로 합치면 layer 도 1개 된다.
RUN apt-get update && apt-get install -y gcc && apt-get install -y git

# 자주 내용이 바뀔 수 있는 COPY 명령은 변경이 있을 때마다 새로 layer 생성을 위해 빌드 시간이 추가되기 때문에 변경이 없는 명령 이후에 위치하여 불필요한 빌드 시간을 단축하는것이 좋다.

# 멀티 스테이지 사용하기
# Docker 17.05 부터 Dockerfile 하나에 여러개의 빌드 스테이지를 둘 수 있다.
# FROM 만큼 스테이지를 생성(이미지 빌드)하고
# 이전 스테이지의 결과를 다음 스테이즈로 복사해서 사용할 수 있다.
# 스테이지1) 소스 빌드 바이너리 --> 스테이지2) 바이너리만 포함된 이미지
# 와 같은 작업을 dockerfile 하나로 작성할 수 있어 편하다.

# Dockerfile
# buildstage 이름의 스테이지로 지정
FROM ubuntu:latest AS buildstage

WORKDIR /root
RUN echo "test" > output.txt

# 만약 또다른 스테이지(buildstage123)가 있으면 이 buildstage, buildstage123 스테이지 둘다 동시에 진행되고,   
# buildstage 에서 다음과 같이 buildstage123 의 결과물을 복사명령이 있다면 buildstage123 가 완료 후 COPY 가 수행된다.
# COPY --from=buildstage123 /xxx.txt .

##########

# 마지막 스테이지
FROM archlinux/base:latest

# buildstage 의 결과물을 현재 스테이지의 . 위치로 복사
COPY --from=buildstage /root/output.txt .
CMD ["/bin/bash"]

# multistage 를 빌드하면 최종 스테이지 말고는 
# 모두 <none> dangling 이미지가 생성되니 지워준다.
# docker image prune -f

# 참고로 dive(https://github.com/wagoodman/dive) 툴을 이용하면 docker image layer 별 사이즈 및 세부내용을 볼수 있어 이미지 분석에 도움이 된다.

comments:

댓글 쓰기