[도커] 4장 애플리케이션 소스 코드에서 도커 이미지 까지

공효은·2023년 5월 19일
0

도커

목록 보기
7/12
post-thumbnail

4.1 Dockerfile이 있는데 빌드 서버가 필요할까?

빌드: 서버에 올릴 수 있는 상태로 만드는 것이다.

  • 대부분의 프로그래밍 언어는 프로젝트를 빌드하기 위해 다양한 도구가 필요하다.
  • 소프트웨어 프로젝트를 빌드하려면 개발 팀원 모두가 같은 도구를 사용해야한다.
  • 개발팀과 빌드 서버는 모든 도구를 같은 버전으로 사용해야한다. 이 과정에서는 유지보수를 위한 큰 오버헤드가 발생한다.
  • 작업용 컴퓨터에서 이들 도구 중 하나를 업데이트하면서 빌드 서버와 버전이 달라지는 것 만으로도 빌드가 실패할 수 있다.

이런 경우에 빌드 툴체인을 한 번에 패키징해서 공유할 수 있다면 편리할 것이다. 도커를 사용하면 가능하다.

  1. 개발에 필요한 모든 도구를 배포하는 Dockerfile 스크립트를 작성한 다음 이를 이미지로 만든다.
  2. 어플리케이션 패키징을 위한 Dockerfile 스크립트에서 이 이미지를 사용해 소스 코드를 컴파일함으로써 애플리케이션을 패키징하는 것이다.

아래예제는 이러한 워크플로를 적용한 기본적인 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 출력 내용으로 파일을 이어쓰기로 저장된다.
  • 이 스크립트는 빌드가 여러 단계로 나뉘는 멀티 스테이지 빌드를 적용한 것이다.
  • 각 빌드 단계는 FROM 인스트럭션으로 시작된다. 필요한 경우 빌드 단계에 AS 파라미터를 이용해 이름을 붙일 수도 있다.
  • 세 단계로 나뉜 멀티 스테이지 빌드의 예이다. 최종 산출물은 마지막 단계의 내용물을 담은 도커 이미지다.
  • 각 빌드 단계는 독립적으로 실행되지만, 앞선 단계에서 만들어진 디렉터리나 파일을 복사할 수 있다. 예제의 COPY 인스트럭션을 보면 --from 인자를 사용해 해당 파일이 호스트 컴퓨터의 파일 시스템이 아니라 앞선 빌드 단계의 파일 시스템에 있는 파일임을 알려준다.
  • 이 예제에서는 build-stage 단계에서 파일 하나를 생성하는데, 이 파일을 test-stage로 복사하고 다시 test-stage에서 생성한 파일을 마지막 단계로 복사한다.

RUN: 파일을 생성하기 위해 사용함. 빌드 중에 컨테이너 안에서 명령을 실행한 다음 그 결과를 이미지 레이어에 저장하는 기능을 한다.
RUN 인스트럭션에서 실행 할 수 있는 명령에는 특별한 제한이 없지만, FROM 인스트럭션에서 지정한 이미지에서 실행할 수 있는 것이어야한다.
여기서는 diamol/base를 기반 이미지로 지정했으며, 이 이미지가 echo 명령을 포함하고 있기 떄문에 이 RUN 인스트럭션이 정상적으로 동작한다.

멀티 스테이지 빌드를 적용한 Dockerfile 스크립트의 실행과정

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 에서 테스트까지 성공적으로 마친 바이너리를 이 이미지에 복사해 넣는다.

4.3 애플리케이션 빌드 실전 예제: Node.js 소스코드

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/ .
  • 이 스크립트의 목표는 애플리케이션을 패키징하고 다른 도구 없이 도커만 설치된 환경에서 애플리케이션을 실행하는것이다.
  • 두 이미지 모두 diamol/node를 기반 이미지로 사용한다. 이 이미지는 Node.js 런타임과 npm이 설치된 이미지다.
  • builder 단계에서 애플리케이션의 의존 모듈이 정의된 package.json 파일을 복사한 다음, npm install 명령을 실행해 의존 모듈을 내려받는다.
  • 이 Node.js 애플리케이션 역시 REST API 이다. 최종 단계에서 공개할 HTTP 포트와 애플리케이션 시작 명령을 지정한다.
  • 최종 단계는 작업 디렉터리를 만들고 호스트 컴퓨터로부터(?) 애플리케이션 아티팩트를 모두 복사해 넣는 것으로 끝난다.
  • src 디렉터리는 애플리케이션의 진입점 역할을 하는 server.js 파일을 비롯해 여러 자바스크립트 파일을 담고 있다.

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

4.5 멀티 스테이지 Dockfile 스크립트 이해하기

장점 1 : 표준화

  • 모든 빌드 과정은 도커 컨테이너 내부에서 이뤄진다. 그리고 이들 컨테이너는 모든 도구를 정확한 버전으로 갖추고 있따.
  • 실무에 적용하면 신규 개발자의 적응 기간이나 빌드 서버의 관리 부담, 혹은 개발자 간 도구 버전의 차이로 인한 빌드 실패를 줄일 수 있다.

장점 2: 성능 향상

  • 멀티 스테이지 빌드의 각 단계는 자신만의 캐시를 따로 갖는다. 그리고 도커는 빌드 중에 각 인스트럭션에 해당하는 레이어 케시를 찾는다.
  • 처음에 Dockerfile 를 최적화하면 캐시 재사용을 통해 90% 이상의 빌드 단계에서 시간을 절약할 수 있다.

장점 3 : 이미지를 가능한 작게 유지할 수 있다.

  • 멀티 스테이지 Dockerfile 스크립트를 통해 빌드 과정을 세밀하게 조정하며 최종 산출물인 이미지를 가능한 작게 유지할 수 있다.
  • 어떤 도구 든지 그 도구가 사용되는 단계만으로 도구의 포함 여부를 국한 시킬 수 있다. 최종 산출물인 이미지에 불필요한 도구는 빼버릴 수 있는것이다.
profile
잼나게 코딩하면서 살고 싶어요 ^O^/

0개의 댓글