Multi-stage build
애플리케이션 개발 시 개발 환경에서 사용한 라이브러리나 개발 지원 툴이 제품 환경에서 반드시 사용되는 것은 아니다. 제품 환경에서 애플리케이션을 실행하기 위해서 최소한으로 필요한 실행 모듈만 배치하는 것이 컴퓨터를 효율적으로 활용하는 데 도움이 된다.
# Multi-stage build
여러번 빌드를 거쳐 도커 이미지의 용량을 최소화 하는 것. 컨테이너 이미지를 만들면서 빌드 등에는 필요하다. 하지만 최종 컨테이너 이미지에는 필요 없는 환경을 제거할 수 있로고 단계를 나우워 기반 이미지를 만드는 것이 좋다.
멀티스테이지 빌드를 사용하게 되면 그림처럼 컨테이너 실행 시에는 빌드에 사용한 파일 및 디렉토리와 같은 의존 파일들이 모드 삭제된 상태로 컨테이너가 실행하게 되고, 좀 더 가벼운 크기의 컨테이너를 사용할 수 있다.
Multi-Stage Bild 실습
# 1. Docker GO - Multi-Stage Build
GO 애플리케이션을 Docker 컨테이너로 배포하기 위해 단일 단계 빌드 와 멀티 단계 빌드를 사용하여 멀티 단계와 단일 단계의 차이점을 이해하고 멀티 단계 빌드를 사용하여 컨테이너 이미지 크기를 줄여볼 것이다.
# 단일 단계 빌드 Dockerfile 작성
ubuntu@docker:~/ch11/multi-stage$ vim dockerfile-go1
FROM golang:1.15-alpine3.12
WORKDIR /app
COPY gostart.go .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /app/gostart
ENTRYPOINT ["/app/gostart"]
# 멀티 단계 빌드 Dockerfile 작성
## stage1
FROM golang:1.15-alpine3.12 AS gobuilder-stage
MAINTAINER "jin <jin@sample.cloud>"
LABEL "purpose"="Application Deployment using Multi-stage builds."
WORKDIR /app/
COPY gostart.go /app/
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /app/gostart
## stage2
FROM scratch
COPY --from=gobuilder-stage /app/gostart /app/gostart
CMD ["/app/gostart"]
단일 단계와 달리 멀티 단계는 두 단계로 구성되어 있다. 첫번째 단계는 빌드 단계로 GO 애플리케이션을 빌드하고, 두 번째 단계에서는 최소한의 빈 이미지를 사용하여 최종적으로 이미지를 생성하고 첫 번째 단계에서 생성한 파일 /app/gostart 파일을 최종 이미지로 복사하여 실행하는 것이다.
# 이미지 비교
ubuntu@docker:~/multi-stage$ docker history goapp:1.0
ubuntu@docker:~/multi-stage$ docker history goapp:2.0
도커 이미지를 비교를 해보면 똑같은 일을 하는데도 용량차이가 많이 난다. 도커 이미지 크기를 줄여야 하는 이유는 도커 이미지 관리할 때 저장 장치(ex: 하드 디스크) 용량을 줄이기 위해 사용한다. 개발자가 아닌 운영팀 입장에서는 도커 이미지 크기를 줄이는 것이 중요한 일 중 하나이다. 애플리케이션 버전별로 도커 이미지를 관리해야 하기 때문이다.
# 컨테이너 실행
ubuntu@docker:~/multi-stage$ docker run --name=goapp1 -p 9091:9090 -d -h goapp1 goapp:1.0
c13e4153bb06c4276b46c58cd1b2968f70e516a2dc13ad27679f5f32c76f87c0
ubuntu@docker:~/multi-stage$ docker run --name=goapp2 -p 9092:9090 -d -h goapp2 goapp:2.0
395bb3772fbc530a75f4fcee88453a5a0c0b6e71f552d58243453e13e12c2458
# 2. Docker shell-scripts - Multi-Stage Build
# 실행할 스크립트 작성
ubuntu@docker:~/multi-stage$ vi appstart.sh
#!/bin/bash
echo "Best image build, multi stage build!"
>> 결과 확인
ubuntu@docker:~/multi-stage$ sh appstart.sh
Best image build, multi stage build!
# 스크립트 실행 권한 부여(퍼미션 변경)
>> 퍼미션 변경전
ubuntu@docker:~/multi-stage$ ll
-rw-rw-r-- 1 ubuntu ubuntu 57 11월 4 11:17 appstart.sh
>> 퍼미션 변경 후
ubuntu@docker:~/multi-stage$ chmod +x appstart.sh
ubuntu@docker:~/multi-stage$ ll
-rwxrwxr-x 1 ubuntu ubuntu 57 11월 4 11:17 appstart.sh*
# 단일 / 멀티 단계 빌드 과정
>>> 단일 단계
ubuntu@docker:~/multi-stage$ vi dockerfile-app1
FROM ubuntu:14.04
RUN apt-get update -y && apt-get install nginx -y
COPY appstart.sh /
RUN useradd user01
USER user01
ENTRYPOINT ["/appstart.sh"]
========================================
>> 멀티 단계
ubuntu@docker:~/multi-stage$ vi dockerfile-app2
FROM ubuntu:14.04 as v1-stage
RUN apt-get update && apt-get install nginx -y
WORKDIR /app
COPY appstart.sh /app
FROM alpine:3.12.1
RUN addgroup -S appgroup && adduser -S user01 -G appgroup -h /home/user01
COPY --from=v1-stage /app /home/user01
USER user01
ENTRYPOINT ["sh","/home/user01/appstart.sh"]
셀 스크립트는 리눅스 명령어니까 bash가 실행된다. bash를 실행하려면 리눅스가 있어야한다.(bash는 독립할 수 없기 때문)
#이미지 빌드(크기 보고 싶으면 --no-cache 제외)
ubuntu@docker:~/multi-stage$ docker build -t webapp:1.0 -f dockerfile-app1 --no-cache .
ubuntu@docker:~/multi-stage$ docker build -t webapp:2.0 -f dockerfile-app2 --no-cache .
>>설치 후 용량 확인
ubuntu@docker:~/multi-stage$ docker history webapp:1.0, 2.0
'OS > Docker' 카테고리의 다른 글
[Docker] Docker Compose (0) | 2024.11.04 |
---|---|
[Docker] Python Flask 웹 서비스 배포 (1) | 2024.11.04 |
[Docker] 데이터 지속성을 위한 Volume 구성 (0) | 2024.10.30 |
[Docker] scratch 이미지 경량화 (3) | 2024.10.28 |
[Docker] 이미지 경량화 (1) | 2024.10.28 |