목차
- Dockerfile이 있는데 빌드 서버가 필요할까?
- 애플리케이션 빌드 실전예제: Node.js 소스 코드
- 멀티 스테이지 Dockerfile 스크립트 이해하기
- 연습: 멀티 스테이지 빌드와 Dockerfile 스크립트 최적화
Dockerfile이 있는데 빌드 서버가 필요할까?
대부분의 프로그래밍 언어는 프로젝트를 빌드하기 위해 다양한 도구가 필요함
- 신규로 참여한 개발자는 이 도구를 설치하는데 시간을 허비 할 수 있다. ( 빌드 서버와 버전이 달라지는 것만으로 빌드가 실패 할 수 있음)
이런 경우에 빌드 툴 체인을 한 번에 패키딩해서 공유할 수 있다면 편하다 → Dockerfile 스크립트
1. 개발에 필요한 모든 도구를 배포하는 Dockerfile 스크립트 작성하여 모두 이미지로 만든다.
2. 애플리케이션 패키징을 위한 Dockerfile 스크립트에서 이 이미지를 사용해 소스 코드를 컴파일함으써 애플리케이션을 패키징
위의 워크플로(멀티 스테이지 빌드)를 적용한 Dockerfile 스크립트
FROM diamol/base AS build-stage
RUN echo 'Building...' > /build.txt
FROM diamol/base AS test-stage
COPY --from=build-stage /build.txt /build.txt
RUN echo 'Building...' >> /build.txt
FROM diamol/base
COPY --from=test-stage /build.txt /build.txt
CMD cat /build.txt
- 모든 stage 는 FROM 으로 시작하는데 빌드 단계에 필요에 의해 AS 를 이용하여 이름을 붙일 수 있다.
실행과정을 표현한 그림 - 각 빌드 단계는 서로 격리돼 있다.
현재 폴더에 있는 Dockerfile 실행하여 multi-stage 이미지 빌드
docker image build -t multi-stage .
- build-stage = 빌드 도구가 설치된 기반 이미지를 사용하여 빌드
- test-stage = 빌드한 바이너리를 복사해서 단위 테스를 수행
- 마지막으로 build-stage 에서 빌드하고 test-stage에서 테스트까지 성공적으로 마친 바이너리를 이 이미지에 복사해서 넣는다.
이 과정을 표현한 그림
애플리케이션 빌드 실전예제: Node.js 소스 코드
컨테이너화된 Node.js 애플리케이션을 실행하려면
- Node.js 런타임 과 소스 코드가 애플리케이션 이미지에 포함되어야 함.
(ch04/exercises/access-log 에 있는 파일)
npm 을 사용해 Node.js 애플리케이션을 빌드하는 Dokcerfile 스크립트
FROM diamol/node AS builder
WORKDIR /src
COPY src/package.json .
RUN npm install
# app
FROM diamol/node
EXPOSE 80
CMD ["node", "server.js"]
WORKDIR /app
COPY --from=builder /src/node_modules/ /app/node_modules/
COPY src/ .
1. Dockerfile 실행하여 이미지 빌드
docker image build -t access-log .
2. 빌드 한 access-log 이미지로 컨테이너로 실행, 이 컨테이너를 nat 네트워크에 연결하며 80번 포트를 공개하라.
docker container run --name accesslog -d -p 801:80 --network nat access-log
- -d (Detached mode) = 백그라운드에서 실행
- -p = 포트 맵핑
- 이때 "docker: Error response from daemon: network nat not found." 라는 문구가 뜰 수 있다.
docker network ls
이용해서 네트워크를 확인하여 nat 의 존재 여부를 한 번더 확인 후 없으면
nat 생성 후 다시 2번 에서 실행된 명령어 실행
docker network create -d bridge nat
성공적으로 이미지가 컨테이너에 담기면
http://localhost:801/stats 에 접속하여 결과를 확인
멀티 스테이지 Dockerfile 스크립트 이해하기
컨테이너 안에서 애플리케이션을 빌드하는 것이 유용한 이유
- 표준화 = 어떤 운영체제를 사용하든 모든 과정은 도커 컨테이너 내부에서 이루어 진다.
- 컨테이너가 빌드하기 위한 모든 도구들의 정확한 버전을 보유하고 있으므로 빌드 실패를 크게 줄인다.
- 성능향상 = 멀티 스테이지 빌드의 각 단계는 자신만의 캐시를 따로 갖는다.
- 처음에 Dockerfile 스크립트를 세심하게 최적화해서 작성한다면 이후로 캐시 재사용을 통해 90% 이상의 빌드 단계에서 시간을 절약할 수 있다. - 이유 : 빌드 중에 각 인트스럭션에 해당하는 레이어 캐시를 보유(3장에서 자세한 내용참고)
- 빌드 과정의 세밀한 조정하며 이미지를 가능한 한 작게 유지 가능
- 예 ) curl 을 이용하여 인터넷을 통해 필요한 파일을 다운 받는다. 이 과정을 빌드 초기 단계에 모아 놓는다면 최종 이미제는 curl 을 포함시키지 않아도 된다. → 이미지 크기 줄여서 애플리케이션 시작 시간을 단축 가능
연습: 멀티 스테이지 빌드와 Dockerfile 스크립트 최적화
Dockerfile 스트크립트
FROM diamol/golang
WORKDIR web
COPY index.html .
COPY main.go .
RUN go build -o /web/server
RUN chmod +x /web/server
CMD ["/web/server"]
ENV USER=sixeyed
EXPOSE 80
해결해야 할 문제
- 지금 있는 Dockerfile 스크립트로 이미지를 빌드한다. 이어서 Dockerfile 스크립트를 최적화한 다음 새로운 이미지를 빌드하라.
- 현재 이미지는 리눅스 환경에서 약 800MB, 윈도 환경에서 약 5.2GB 크기다. 최적화 된 이미지의 크기는 리눅스 환경에서 약 15MB, 윈도 환경에서 약 260MB가 되도록하라.
- 현재 Dockerfile 스크립트에 포함된 HTML 파일의 내용을 수정하면 7 단계의 빌드 단계를 재수행한다.
- Dockerfile 스크립트를 최적화해서 HTML 파일을 수정하더라도 재수행하는 빌드 단계가 한 단계가 되도록 하라.
[힌트] 주어진 Dockerfile 스트크립트와 같은 애플리케이션을 실행하는 Dockerfile
FROM diamol/golang AS builder
COPY main.go .
RUN go build -o /server
# app
FROM diamol/base
ENV IMAGE_API_URL="http://iotd/image" \
ACCESS_API_URL="http://accesslog/access-log"
CMD ["/web/server"]
WORKDIR /web
COPY index.html .
COPY --from=builder /server .
RUN chmod +x server
최적화 후
FROM diamol/golang AS builder
COPY main.go .
RUN go build -o /server
RUN chmod +x /server
# 프로덕션 이미지
FROM diamol/base
EXPOSE 80
CMD ["/web/server"]
ENV USER="sixeyed"
WORKDIR web
COPY --from=builder /server .
COPY index.html .
설명
- 멀티 스테이지 이용하여 이미지의 크기 감소
- builder 스테이지에서 빌드된 바이너리를 프로덕션 스테이지로 복사
- builder 스테이지에서 필요한 도구와 라이브러리를 설치
- diamol/golang 이미지를 기반으로 하고, main.go 파일을 복사한 후 /server로 실행 파일을 빌드
- 프로덕션 스테이지에서 index.html과 /server만 포함되므로 더 경량화된 이미지 생성가능
- builder 스테이지에서 필요한 도구와 라이브러리를 설치
- builder 스테이지에서 빌드된 바이너리를 프로덕션 스테이지로 복사
- builder 스테이지에서 권한을 부여하여 중복되는 작업 제거
- RUN chmod +x /server를 통해 실행 권한을 부여 (빌드과정에서 부여하는 것이 적합)
- 이유 = 빌드 과정에서 파일의 실행 권한을 한 번 설정하면, 이후 단계에서 반복적으로 설정할 필요가 없다. 즉, 빌드 과정에서 chmod +x를 실행하면, 해당 명령이 한 번만 실행되고 이후 단계에서는 캐시를 재사용
- 멀티 스테이지 이용하여 중복될수 있는 문제 해결
- builder 스테이지에서 권한을 부여하여 중복되는 작업 제거
- RUN chmod +x /server를 통해 실행 권한을 부여 (빌드과정에서 부여하는 것이 적합)
- 이유 = 빌드 과정에서 파일의 실행 권한을 한 번 설정하면, 이후 단계에서 반복적으로 설정할 필요가 없다. 즉, 빌드 과정에서 chmod +x를 실행하면, 해당 명령이 한 번만 실행되고 이후 단계에서는 캐시를 재사용
- RUN chmod +x /server를 통해 실행 권한을 부여 (빌드과정에서 부여하는 것이 적합)
- ENV와 WORKDIR를 프로덕션 스테이지에 배치하여 중복 작업 방지
- 프로덕션 단계에만 필요한 설정(ENV, WORKDIR)은 빌더 단계에서 실행할 필요가 없으므로, 프로덕션 스테이지에 배치하여 불필요한 중복 작업을 제거
- 불필요한 이미지 레이어 생성 방지
- Docker는 각 명령어(RUN, COPY, ENV, WORKDIR 등)를 실행할 때마다 새로운 이미지 레이어를 생성
- builder 와 프로덕션 스테이지 구별이 없으므로 불필요한 레이어 생성 → 이미지 전체에 영향
- builder 스테이지에서 권한을 부여하여 중복되는 작업 제거
'책 > 도커 교과서' 카테고리의 다른 글
[ 책 ] [ 도커교과서 ] 7장 도커 컴포즈 분산 애플리케이션 실행하기 (0) | 2024.12.23 |
---|---|
[책] [ 도커교과서 ] 6장 도커 볼륨을 이용한 퍼시스턴트 스토리지 (0) | 2024.12.15 |
[책] [ 도커교과서 ] 5장 도커 허브 등 레지스트리에 이미지 공유하기 (0) | 2024.12.13 |
[ 책 ] [ 도커교과서 ] 3장 도커 이미지 만들기 (0) | 2024.12.08 |
[ 책 ] [ 도커교과서 ] 1장 (0) | 2024.12.02 |