ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Dockerfile
    BackEnd/docker 2022. 3. 16. 22:33
    반응형

      개발한 애플리케이션을 컨테이너화할 때 가장 먼저 생각나는 방법은 아래와 같습니다.

    1. 아무것도 존재하지 않는 이미지(우분투, CentOS 등)로 컨테이너를 생성

    2. 애플리케이션을 위한 환경을 설치하고 소스코드 등을 복사해 잘 동작하는 것을 확인

    3. 컨테이너를 이미지로 커밋(commit)

      위와 같은 방법을 사용하면 애플리케이션이 동작하는 환경을 구성하기 위해 일일이 수작업으로 패키지를 설치하고 소스코드를 깃(Git)에서 복제하거나 호스트에서 복사해야 합니다.

     

      도커는 위와 같은 일련의 과정을 손쉽게 기록하고 수행할 수 있는 빌드(build) 명령어를 제공합니다. 완성된 이미지를 생성하기 위해 컨테이너에 설치해야 하는 패키지, 추가해야 하는 소스코드, 실행해야 하는 명령어와 셸 스크립트 등을 하나의 파일에 기록해 두면 도커는 이 파일을 읽어 컨테이너에서 작업을 수행한 뒤 이미지로 만들어 냅니다. 이러한 작업을 기록한 파일의 이름을 Dockerfile이라 하며, 빌드 명령어는 Dockerfile을 읽어 이미지를 생성합니다. Dockerfile을 사용하면 깃과 같은 개발 도구를 통해 애플리케이션의 빌드 및 배포를 자동화할 수 있습니다.

     

      애플리케이션을 컨테이너화하기 위한 장기적인 관점에서 본다면 Dockerfile을 작성하는 것은 이미지를 생성하는 방법을 기록하는 것뿐만 아니라 이미지의 빌드, 배포 측면에서도 매우 유리합니다. 애플리케이션에 필요한 패키지 설치 등을 명확히 할 수 있고 이미지 생성을 자동화할 수 있으며, 쉽게 배포할 수 있기 때문입니다.

     

    Dockerfile 작성

      먼저 사용할 디렉터리를 생성하고 디렉터리 안에 HTML 파일을 만듭니다.

    $ mkdir dockerfile && cd dockerfile
    $ echo test >> test.html
    
    $ ls
    test.html

      Dockerfile을 작성합니다. 아래의 Dockerfile은 이미지에 아파치 웹 서버를 설치한 뒤, 로컬에 있는 test.html 파일을 웹 서버로 접근할 수 있는 컨테이너의 디렉터리인 /var/www/html에 복사합니다.

    $ vi Dockerfile
    
    FROM ubuntu:14.04
    MAINTAINER hanseomkim
    LABEL "purpose"="practice"
    RUN apt-get update
    RUN apt-get install apache2 -y
    ADD test.html /var/www/html
    WORKDIR /var/www/html
    RUN ["/bin/bash", "-c", "echo hello >> test2.html"]
    EXPOSE 80
    CMD apachectl -DFOREGROUND

      Dockerfile은 한 줄이 하나의 명령어가 되고, 명령어(Instruction)를 명시한 뒤에 옵션을 추가하는 방식입니다. 명령어를 소문자로 표기해도 상관은 없지만 일반적으로 대문자로 표기합니다. Dockerfile의 명령어는 위에서 아래로 한 줄씩 차례대로 실행됩니다.

    • FROM: 생성할 이미지의 베이스가 될 이미지를 뜻합니다. FROM 명령어는 Dockerfile을 작성할 때 반드시 한 번 이상 입력해야 하며, 이미지 이름의 포맷은 docker run 명령어에서 이미지 이름을 사용했을 때와 같습니다.
    • MAINTAINER: 이미지를 생성한 개발자의 정보를 나타냅니다. 1.13.0 버전 이후 사용하지 않으며, 아래와 같이 LABEL로 교체해 표현할 수 있습니다.
    LABEL maintainer "hanseomkim <hanseomkim@gmail.com>"
    • LABEL: 이미지에 메타데이터를 추가합니다('키:값' 형태). 라벨은 부가적인 정보를 부여함으로써 원하는 조건의 컨테이너, 이미지 등을 쉽게 찾을 수 있도록 도와줍니다. docker run 명령어에서 --label 옵션을 사용할 수 있으며 docker ps에서 --filter 옵션을 적용할 수 있습니다.
    • RUN: 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행합니다.
    • ADD: 파일을 이미지에 추가합니다. 추가할 파일명은 여러 개를 지정할 수 있으며 배열의 마지막 원소가 컨테이너에 추가될 위치입니다.
    • WORKDIR: 명령어를 실행할 디렉터리를 나타냅니다. 배시 셸에서 cd 명령어를 입력하는 것과 같은 기능을 합니다.
    • EXPOSE: Dockerfile의 빌드로 생성된 이미지에서 노출할 포트를 설정합니다.
    • CMD: 컨테이너가 시작될 때마다 실행할 명령어(Command)를 설정하며, Dockerfile에서 한 번만 사용할 수 있습니다. apachectl -DFOREGROUND 커맨드가 적용되어 컨테이너가 시작될 때 자동으로 아파치 웹 서버가 실행될 것입니다.

     

    Docker 빌드

      docker build 명령어를 사용하여 mybuild:0.0 이름의 이미지를 생성합니다.

    $ docker build -t mybuild:0.0 ./
    • -f or --file: Dockerfile의 이름을 지정합니다. (docker build -f Dockerfile2 -t mybuild:0.0 ./)
    • -t: 생성될 이미지의 이름을 설정합니다.
    • ./: build 명령어 끝에는 Dockerfile이 저장된 경로를 입력합니다.

     

      다음 명령어를 입력해 생성된 이미지로 컨테이너를 실행합니다.

    $ docker run -d -P --name myserver mybuild:0.0
    01c6e07ceed41fec9c9f26f52c6c8f7cfccaab0887353b6094424934962ebf71
    • -P: 이미지에 설정된 EXPOSE의 모든 포트를 호스트에 연결하도록 설정합니다.

     

      docker ps 또는 docker port 명령어로 컨테이너와 연결된 호스트의 포트를 확인할 수 있으며, 호스트의 IP와 포트로 컨테이너의 웹 서버에 접근할 수 있습니다.

    $ docker port myserver
    80/tcp -> 0.0.0.0:55000

    localhost:55000/test.html

     

    빌드 과정

      이미지 빌드를 시작하면 도커는 가장 먼저 빌드 컨텍스트를 읽어 들입니다. 빌드 컨텍스트는 이미지를 생성하는 데 필요한 각종 파일, 소스코드, 메타데이터 등을 담고 있는 디렉터리를 의미하며, Dockerfile이 위치한 디렉터리가 빌드 컨텍스트가 됩니다. 컨텍스트는 build 명령어의 맨 마지막에 지정된 위치에 있는 파일을 전부 포함합니다. 깃(Git)과 같은 외부 URL에서 Dockerfile을 읽어 들인다면 해당 저장소(Repository)에 있는 파일과 서브 모듈을 포함합니다. 따라서 Dockerfile이 위치한 곳에는 이미지 빌드에 필요한 파일만 있는 것이 바람직하며, 루트 디렉터리(/)와 같은 곳에서 이미지를 빌드하지 않도록 주의해야 합니다. 빌드에 불필요한 파일이 포함된다면 빌드 속도가 느려질뿐더러 호스트의 메모리를 지나치게 점유할 수도 있습니다.

     

      build 명령어는 Dockerfile에 기록된 대로 컨테이너를 실행한 뒤 완성된 이미지를 만들어 냅니다. 이미지로 만드는 과정은 Dockerfile에서 명령어 한 줄이 실행될 때마다 이전 Step에서 생성된 이미지에 의해 새로운 컨테이너가 생성되며, Dockerfile에 적힌 명령어를 수행하고 다시 새로운 이미지 레이어로 저장됩니다. 따라서 이미지의 빌드가 완료되면 Dockerfile의 명령어 줄 수만큼의 레이어가 존재하게 되며, 중간에 컨테이너도 같은 수만큼 생성되고 삭제됩니다. (이미지 레이어 수를 줄이기 위해서는 &&로 각 RUN 명령을 하나로 묶으면 됩니다.)

     

      한 번 이미지 빌드를 마치고 난 뒤 다시 같은 빌드를 진행하면 이전의 이미지 빌드에서 사용했던 캐시를 사용합니다. 그러나 깃허브 같은 소스코드 저장소에서 git clone 등의 명령어를 사용해 이미지를 빌드했다면 RUN에 대한 이미지 레이어를 계속 캐시로 사용하기 때문에 실제 깃 저장소에서 리비전 관리가 일어나도 매번 빌드를 할 때마다 고정된 소스코드를 사용하게 될 것입니다. 이 경우 캐시를 사용하지 않기 위해 --no-cache 옵션을 추가합니다.

    $ docker build --no-cache -t mybuild:0.0 .

     

    .dockerignore 파일

      깃에서 사용하는 .gitignore와 유사한 기능을 사용할 수 있습니다. .dockerignore라는 파일을 작성하면 빌드 시 이 파일에 명시된 이름의 파일을 컨텍스트에서 제외합니다. .dockerignore 파일은 컨텍스트의 최상위 경로, 즉 build 명령어에서 맨 마지막에 오는 경로인 Dockerfile이 위치한 경로와 같은 곳에 위치해야 합니다.

    $ vi .dockerignore
    test2.html
    *.html
    */*.html
    test.htm?
    !test*.html

      '?'는 임의의 1자리 문자를 의미하며, '!'는 특정 파일을 제외하지 않음을 뜻합니다.

     

    멀티 스테이지(Multi-stage) 빌드

      17.05 버전 이상을 사용하는 도커 엔진이라면 멀티 스테이지 빌드 방법을 사용할 수 있습니다. 멀티 스테이지 빌드는 하나의 Dockerfile 안에 여러 개의 FROM 이미지를 정의함으로써 빌드 완료 시 최종적으로 생성될 이미지의 크기를 줄이는 역할을 합니다. 각 이미지는 먼저 FROM에서 명시된 순서대로 0, 1..의 순으로 차례대로 구분되어 사용됩니다.

    FROM golang
    ADD main.go /root
    WORKDIR /root
    RUN go build -o /root/mainApp /root/main.go
    
    FROM golang
    ADD main2.go /root
    WORKDIR /root
    RUN go build -o /root/mainApp2 /root/main2.go
    
    FROM alpine:latest
    WORKDIR /root
    COPY --from=0 /root/mainApp .
    COPY --from=1 /root/mainApp2 .
    반응형

    'BackEnd > docker' 카테고리의 다른 글

    도커 데몬(Docker Daemon)  (0) 2022.03.19
    Dockerfile 명령어  (0) 2022.03.18
    이미지 배포(Image Deploy)  (0) 2022.03.15
    도커 이미지(Docker Image)  (0) 2022.03.15
    컨테이너 자원 할당 제한  (0) 2022.03.12

    댓글

Designed by Tistory.