Dockerfile 작성하기

라모스·2023년 7월 3일
0
post-thumbnail

Dockerfile은 애플리케이션을 패키징하기 위한 간단한 스크립트다.

  • Dockerfile은 일련의 인스트럭션으로 구성되어 있다. 인스트럭션을 실행한 결과로 Docker Image가 만들어진다.
  • 자주 쓰이는 작업은 별도의 명령이 마련돼 있다.
  • 원하는 작업을 직접 작성할 수 있고, 표준 셸 문법도 사용 가능하다.

Dockerfile 문법

예시는 다음과 같다.

FROM diamol/node

ENV TARGET="www.google.com"
ENV METHOD="HEAD"
ENV INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .

CMD ["node", "/web-ping/app.js"]

위 스크립트에 나온 인스트럭션은 대문자로 작성돼 있으나 소문자를 사용해도 무방하다.

  • FROM: 모든 이미지는 다른 이미지로부터 출발한다. 위 이미지는 diamol/node 이미지를 시작점으로 지정했다. 해당 이미지에는 web-ping 애플리케이션을 실행하는 데 필요한 런타임인 Node.js가 설치돼 있다.
  • ENV: 환경 변수 값을 지정하기 위한 인스트럭션이다. 값을 지정하기 위해 [key]="[value]" 형식을 따른다.
  • WORKDIR: 컨테이너 이미지 파일 시스템에 디렉터리를 만들고, 해당 디렉터리를 작업 디렉터리로 지정하는 인스트럭션이다.
    • Linux와 Windows 컨테이너 모두 구분자로 슬래시를 사용한다.
  • COPY: 로컬 파일 시스템의 파일 혹은 디렉터리를 컨테이너 이미지로 복사하는 인스트럭션이다.
    • [원본경로] [복사경로] 형식으로 지정하면 된다.
  • CMD: Docker가 이미지로부터 컨테이너를 실행했을 때 명령을 지정하는 인스트럭션이다. 위 예시에선 Node.js 런타임이 애플리케이션을 시작하도록 app.js를 지정했다.

컨테이너 이미지 빌드

이미지를 빌드하기 위해선 Dockerfile 스크립트와 함께 이미지의 이름, 패키징에 필요한 파일의 경로를 지정해야 한다.

docker image build --tag web-ping .
  • --tag: 인잣값은 이미지의 이름
  • .: Dockerfile 및 이미지에 포함 시킬 파일이 위치한 경로. Docker에선 이 디렉터리를 컨텍스트라고 한다. 위 예시에선 현재 작업 디렉터리를 의미함.

build 명령을 입력하면 Dockerfile 스크립트에 포함된 인스트럭션이 차례로 실행되며 그 결과가 출력된다.

참고로, Docker는 빌드 컨텍스트 정보를 필요로 하기 때문에 명령 마지막에 작업 디렉터리를 반드시 빼먹으면 안된다.

출력 마지막에 'successfully built', 'successfully tagged' 라는 메시지가 출력됐다면, 이미지를 성공적으로 빌드한 것이다. 빌드된 이미지는 로컬 이미지 캐시에 저장되며 Docker 명령으로 이미지 목록을 확인하면 볼 수 있다.

Docker image와 image layer

Docker image에는 우리가 패키징에 포함시킨 모든 파일이 들어 있다. 이들 파일은 나중에 컨테이너의 파일 시스템을 형성한다.

이 외에도 image에는 자신에 대한 여러 메타데이터 정보도 들어 있다. 이 정보 중에는 image가 어떻게 빌드됐는지에 대한 간단한 이력도 포함된다. 이를 이용하면 image를 구성하는 각 레이어는 무엇이고 이들 레이어가 어떤 명령으로 빌드됐는지 알 수 있다.

> docker image history web-ping
IMAGE         CREATED        CREATED BY
47eeeb7cd600  30 hours ago   /bin/sh -c #(nop) CMD ["node" "/web-ping/ap...
<missing>     30 hours ago   /bin/sh -c #(nop) COPY file:a7cae366c9996502...
<missing>     30 hours ago   /bin/sh -c #(nop) WORKDIR /web-ping

CREATED BY 항목은 해당 레이어를 구성한 Dockerfile 스크립트의 인스트럭션이다. Dockerfile 인스트럭션과 image layer는 1:1 관계를 갖는다.

Docker image는 image layer가 모인 논리적 대상이다. 레이어는 Docker 엔진의 캐시에 물리적으로 저장된 파일이다. image layer에는 여러 image와 컨테이너에서 공유된다.

예를 들어, Node.js 애플리케이션이 실행되는 컨테이너를 여러 개 실행한다면 이들 컨테이너는 모두 Node.js 런타임이 들어 있는 image layer를 공유한다.

web-ping 이미지 예시는 diamol/node 이미지를 기반 이미지로 하므로 기반 이미지의 모든 레이어를 포함한다. Dockerfile 스크립트의 FROM 인스트럭션의 의미는 바로 이것이다.

이런 방식으로 이미지끼리 레이어를 공유하여, 디스크 공간이 절약된다.

이미지 레이어를 여러 이미지가 공유한다면, 공유되는 레이어는 수정할 수 없어야 한다. 만약, 이미지의 레이어를 수정할 수 있다면 그 수정이 레이어를 공유하는 다른 이미지에도 영향을 미치게 된다.
Docker는 이미지 레이어를 읽기 전용으로 만들어 두어 이런 문제를 방지한다. 이미지를 build하면서 레이어가 만들어지면, 레이어는 다른 이미지에서 재사용될 수 있다. 그러나 레이어는 수정할 수는 없다.
이 점은 Dockerfile 스크립트를 최적화해 Docker image의 용량을 줄이고 빌드를 빠르게 만드는 기법에서 특히 잘 활용된다.

References

profile
블로그 이전 → https://ramos-log.tistory.com/

0개의 댓글