빌드: 서버에 올릴 수 있는 상태로 만드는 것이다.
이런 경우에 빌드 툴체인을 한 번에 패키징해서 공유할 수 있다면 편리할 것이다. 도커를 사용하면 가능하다.
아래예제는 이러한 워크플로를 적용한 기본적인 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 'Testing...' >> /build.txt
FROM biamol/base
COPY --from=test-stage /build.txt build.txt
CMD cat /build.txt
echo "내용" > {파일명}
- 해당 경로에 파일명이 존재하지 않으면 echo 출력 내용으로 새로 파일을 생성한다.
- 해당 경로에 파일명이 존재한다면 echo 출력 내용으로 파일을 덮어쓰기로 저장된다.
echo "내용" >> {파일명}
- 해당 경로에 파일명이 존재하지 않으면 echo 출력 내용으로 새로 파일을 생성한다.
- 해당 경로에 파일명이 존재한다면 echo 출력 내용으로 파일을 이어쓰기로 저장된다.
RUN: 파일을 생성하기 위해 사용함. 빌드 중에 컨테이너 안에서 명령을 실행한 다음 그 결과를 이미지 레이어에 저장하는 기능을 한다.
RUN 인스트럭션에서 실행 할 수 있는 명령에는 특별한 제한이 없지만, FROM 인스트럭션에서 지정한 이미지에서 실행할 수 있는 것이어야한다.
여기서는 diamol/base를 기반 이미지로 지정했으며, 이 이미지가 echo 명령을 포함하고 있기 떄문에 이 RUN 인스트럭션이 정상적으로 동작한다.
1단계 빌드에서 텍스트 파일을 생성한다.
2단계 빌드에서는 1단계에서 생성한 텍스트 파일을 복사해온다.
3단계 빌드에서는 2단계에서 생성한 텍스트 파일을 복사해온다.
멀티 스테이지 빌드가 적용된 Dockerfile 스크립트를 사용해 이미지를 빌드해보자.
cd ch04/exercises/multi-stage
docker image build -t multi-stage .
build-stage 단계에서는 빌드 도구가 설치된 기반 이미지를 사용한다. 로컬 컴퓨터에서 소스 코드를 복사해 넣고, build 명령을 실행한다.
단위 테스트 프레임워크가 설치된 기반 이미지를 사용하며 앞서 빌드한 바이너리를 복사해 간 다음 단위 테스트를 수행하는 test-stage 단계를 추가할 수도 있다.
마지막 단계는 애플리케이션을 실행할 런타임이 들어 있는 기반 이미지로 시작한다.
그리고 build-stage에서 빌드하고 test-stage 에서 테스트까지 성공적으로 마친 바이너리를 이 이미지에 복사해 넣는다.
Node.js 애플리케이션은 자바스크립트로 구현된다. 자바스크립트는 인터프리터형 언어로 별도의 컴파일 절차가 필요없다. 컨테이너화된 Node.js 애플리케이션을 실행하려면 Node.js 런타임과 스스코드가 애플리케이션 이미지에 포함돼야한다.
//npm을 사용해 Node.js 애플리케이션을 빌드하는 Dockerfile 스크립트
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/ .
Node.js 애플리케이션의 소스 코드를 훑어보고 이미지를 빌드한다.
COPY --from=builder /src/node_modules/
// 앞서 builder 단계에서 내려받은 의존 모듈을 application 단계에서 복사해온다.
COPY src/ .
// 호스트 컴퓨터의 src 디렉터리에서 자바스크립트 파일을 복사해 온다.
이 애플리케이션은 다른 서비스로부터 호출을 받아 로그를 남기는 REST API다. HTTP POST 엔드포인트를 통해 남길 로그를 접수하며 GET 엔드포인트를 통해 현재까지 기록된 로그 건수를 알려준다.
//지금까지 빌드한 access-log 이미지로 컨테이너를 실행하되, 이 컨테이너를 nat 네트워크에 연결하며 80번 포트를 공개하라.
docker container run --name accesslog -d -p 801:80 --network nat access-log
장점 1 : 표준화
장점 2: 성능 향상
장점 3 : 이미지를 가능한 작게 유지할 수 있다.