티스토리 뷰

반응형

이 글은 '완벽한 IT 인프라 구축을 위한 Docker(Asa Shiho 지음, Yamada Yoshihiro 감수, 신은화 옮김)'  책을 바탕으로 요약 및 실습한 내용을 정리한 글입니다.


 실습 환경 설정

cd /home
mkdir docker

실습을 진행하기 위해 /home 경로에 'docker' 폴더를 하나 만들어주고 모든 실습은 별도로 명시하지 않을 경우 docker 폴더 내에서 진행합니다.



제4장 Dockerfile로 서버 구축

4-1 Dockerfile의 기본

Dockerfile이란?

Dockerfile은 Docker상에서 동작하는 컨테이너 구성 정보를 저장한 파일이다.

docker build 커맨드를 통해 Dockerfile에 저장된 구성 정보를 기반으로 Docker 이미지를 생성한다.


Dockerfile의 용도

커맨드를 사용하여 Docker 이미지를 생성하는 방법은 Docker 이미지를 기반으로 Docker 컨테이너를 생성하고 그 안에서 수동으로 OS와 미들웨어 및 매개변수를 설정했다. 또한 완성된 컨테이너에서 서버를 구축하고 이를 기반으로 다시 Docker 이미지를 생성했다.

따라서 아래의 정보와 함께 인프라 설계서와 매개변수 시트 등의 정보를 별도로 작성해둘 필요가 있다.

  • 기반이 되는 Docker 이미지
  • Docker 컨테이너 안에서 실행되는 커맨드
  • 환경변수 등의 설정
  • Docker 컨테이너 안에서 이루어지는 데몬 실행

Dockerfile 명령어

명령어설명명령어설명
FROM베이스 이미지 지정ADD파일 및 디렉터리 추가
MAINTAINERDockerfile 작성자 저장COPY파일 복사
RUN커맨드 실행VOLUME볼륨 마운트
CMD데몬 실행ENTRYPOINT데몬 실행
LABEL라벨 설정USER사용자 설정
EXPOSE포트 exportWORKDIR작업 디렉터리 지정
ENV환경변수 설정ONBUILDbuild 완료 후 실행될 명령어


Dockerfile 작성

베이스 이미지 : 어떤 Docker 이미지로부터 Docker 컨테이너가 생성되었는가에 대한 정보

FROM

  • FROM은 필수 항목
    FROM [이미지명]
    FROM [이미지명]:[태그명]
    FROM [이미지명]@[Digest]
    
  • 태그명을 생략하면 베이스 이미지의 최신 버전으로 적용
  • 작성자가 이미지명과 태그명에 임의의 값을 넣을 수도 있음
  • Dockerfile을 수정하여 같은 이름의 다른 이미지 생성 가능
  • 특정 이미지를 지정할 때에는 digest 사용. digest는 Docker Hub에 업로드할 때 자동으로 부여받는 식별자를 말함

MAINTAINER

  • Dockerfile 작성자를 저장할 때 사용
    MAINTAINER [Dockerfile 작성자(이름 이메일주소)]
    
  • 필수 값은 아니지만 Docker Hub 등에 이미지를 공개하는 것을 고려하면 입력해두는 것이 좋음

Dockerfile로 Docker 이미지 생성

Dockerfile로 이미지를 생성할 때에는 docker build 커맨드를 사용합니다.

Dockerfile 생성

cd /home/docker
mkdir sample && cd $_
sudo atom Dockerfile

Dockerfile 내용

#베이스 이미지 설정
FROM centos:centos7



docker build 커맨드 실행

#docker build -t [생성할 이미지명]:[태그명] [Dockerfile 경로]
docker build -t sample:1.0 .



최초 실행 이후에는 Docker repository에서 베이스 이미지를 다운로드하지 않고 바로 생성 가능합니다.

로컬 환경에 베이스 이미지가 있을 때에는 베이스 이미지와 새로 생성한 이미지의 ID(IMAGE ID)가 동일합니다. 이는 각 이미지는 서로 다른 이름을 갖고 있으나 그 실체는 같은 이미지라는 것을 의미합니다.

Dockerfile은 파일명을 임의로 지정할 수 있습니다. 파일명을 지정할 때에는 docker build의 f 옵션을 사용합니다. 그러나 파일명이 Dockerfile이 아닌 경우에는 Docker Hub에서 이미지가 자동 생성되지 않으므로 주의해야 합니다.

Dockerfile.base 작성

sudo atom Dockerfile.base

Dockerfile.base 내용

#베이스 이미지 설정
FROM centos:centos7



docker build 커맨드 실행(-f 옵션)

#docker build -t [생성할 이미지명]:[태그명] –f [Dockerfile 파일명] [Dockerfile 경로]
docker build -t sample:2.0 -f Dockerfile.base .




이미지 캐시

Docker는 이미지를 build할 때 자동으로 캐시를 생성하고 다른 이미지를 build할 때 내부의 캐시를 사용하여 build의 속도를 높입니다. 캐시 사용 시에는 build 로그에 'Using cache'가 표시됩니다. 이미지 캐시가 필요 없을 때에는 docker build 커맨드에서 --no-cache 옵션을 사용합니다.


Docker 이미지 레이어 구조

Dockerfile을 기반으로 docker build 커맨드를 실행하여 이미지를 생성하면 다음과 같은 결과가 출력됩니다.



로그를 확인해보면 Dockerfile 명령어의 첫 번째 행부터 실행하여 이미지를 생성하는 것을 알 수 있습니다.

생성된 이미지는 다른 이미지와 공유됩니다. Docker는 이미지를 중첩하여 디스크 용량을 효율적으로 사용합니다.


4-2 커맨드 및 데몬 실행

이미지에서 컨테이너를 생성한 뒤에는 서버 프로세스 등을 데몬으로 실행해야 합니다.

커맨드 실행(RUN)

RUN 명령어로 여러 커맨드를 실행합니다. Dockerfile 생성 시, 이러한 RUN 명령어가 많이 사용됩니다.

RUN [실행하고자 하는 커맨드]

RUN을 실행하는 방법으로는 다음의 두 가지가 있습니다.

Shell 형식으로 실행

아래의 명령어를 실행하면 yum 커맨드로 httpd를 설치할 수 있습니다.

#httpd 설치
RUN yum -y install httpd

Docker 컨테이너에서 /bin/sh -c로 커맨드를 실행시키는 방식과 동일합니다.

Exec 형식으로 실행

Shell 형식의 커맨드는 /bin/sh로 실행시키지만, Exec 형식의 경우 Shell을 거치지 않고 바로 실행시킵니다. 그러므로 커맨드 값에 $HOME 등의 환경변수를 입력할 수 없습니다. Exec 형식에서는 실행하고자 하는 커맨드를 JSON 형식으로 입력합니다.

또한 다른 Shell을 사용하고 싶을 때에는 RUN 명령어에 Shell 경로를 지정하여 실행하고자 하는 커맨드를 입력합니다. 다음을 실행하면 /bin/bash에서 yum 커맨드를 사용하여 httpd를 설치할 수 있습니다.

#httpd 설치
RUN ["/bin/bash", "-c", "yum -y install httpd"]

값에 문자열을 입력할 때에는 '(single quote)를 사용합니다.

RUN 명령은 파일 내에 입력된 명령어를 순서대로 실행합니다.

이미지를 생성할 때 어떤 커맨드가 실행되었는지를 확인하려면 docker history 커맨드를 실행합니다.

docker history [이미지명]

/bin/sh를 통해 커맨드를 실행하고자 할 때에는 Shell 형식을, 그 외에는 Exec 형식을 사용하는 것이 좋습니다.


데몬 실행(CMD)

이미지를 생성하기 위해 실행되는 커맨드는 RUN 명령어에 입력하지만 컨테이너에서 실행되는 커맨드는 CMD 명령어를 사용합니다. Dockerfile에는 한 개의 CMD 명령어만 입력할 수 있으며, 만약 여러 개를 입력한 경우 마지막 커맨드만 적용됩니다.

예를 들어 웹 서버를 구동하기 위하여 httpd를 설치하는 커맨드는 RUN 명령어를 사용하고 컨테이너 내에서 설치한 httpd를 데몬으로 상시 구동하는 것은 CMD 명령어를 사용합니다.

CMD [실행하고자 하는 커맨드]

Shell 형식으로 실행

RUN 명령의 커맨드와 동일합니다.

#httpd를 Foreground에서 실행
CMD /usr/sbin/httpd -D FOREGROUND

Exec 형식으로 실행

RUN 명령의 커맨드와 동일합니다.

#httpd를 Foreground에서 실행
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

ENTRYPOINT 명령어의 매개변수로 실행

ENTRYPOINT 명령어의 값에 CMD 명령어를 입력하여 실행할 수 있습니다.


데몬 실행(ENTRYPOINT)

ENTRYPOINT 명령어에 입력한 커맨드는 docker run 커맨드가 동작할 때 실행됩니다.

ENTRYPOINT [실행하고자 하는 커맨드]

Shell 형식으로 실행

RUN 명령의 커맨드와 동일합니다.

#httpd를 Foreground에서 실행
ENTRYPOINT /usr/sbin/httpd -D FOREGROUND

Exec 형식으로 실행

RUN 명령의 커맨드와 동일합니다.

#httpd를 Foreground에서 실행
ENTRYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"]

CMD와의 차이

ENTRYPOINT 명령과 CMD 명령의 차이는 docker run 커맨드 실행 시점에서의 동작입니다.

CMD 명령은 컨테이너를 구동할 때 정의한 커맨드보다 docker run 커맨드의 값으로 입력된 새로운 커맨드가 우선 실행됩니다.

다음은 최신 버전의 CentOS를 베이스 이미지로 하여 Apache httpd와 nginx를 모두 설치하고 CMD 명령어로 httpd를 구동하는 Dockerfile입니다.

# Docker 이미지
FROM centos:latest

# Apache httpd 설치
RUN ["yum", "-y", "install", "httpd"]

# nginx 설치
RUN ["rpm", "-Uvh", "http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm"]
RUN ["yum", "install", "-y", "nginx"]

# Apache httpd 실행
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]



위의 Dockerfile을 기반으로 sample 이미지를 생성해봅시다.

docker build -t sample .


이 sample 이미지를 기반으로 다음 커맨드를 실행하면 Dockerfile의 CMD 명령에서 입력한 httpd를 Foreground에서 실행하는 컨테이너가 구동됩니다.

docker run -d -p 80:80 sample


브라우저에서 80번 포트로 액세스하면 httpd가 구동되고 있는 것을 확인할 수 있습니다.

sample 이미지를 기반으로 다음 docker run을 실행시켜, 앞서 설치한 nginx로 기동하는 커맨드를 통해 컨테이너를 구동해봅시다. 포트는 81번을 사용합니다.

docker run -d -p 81:80 sample /usr/sbin/nginx -g "daemon off;"

브라우저에서 81번 포트로 액세스하면 nginx가 동작하고 있는 것을 확인할 수 있습니다.


이처럼 CMD 명령은 docker run에서 데몬으로 실행하는 커맨드를 우선시하므로, 컨테이너를 구동할 때 Dockerfile을 생성한 인프라 구축 담당자가 의도하지 않은 데몬이 실행될 수 있습니다. 그러므로 컨테이너 구동 시 특정 데몬을 강제적으로 실행시키고자 할 때에는 ENTRYPOINT를 사용합니다.

앞서 설명한 Dockerfile을 다음과 같이 수정합니다.

# Docker 이미지
FROM centos:latest

# Apache httpd 설치
RUN ["yum", "-y", "install", "httpd"]

# nginx 설치
RUN ["rpm", "-Uvh", "http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm"]
RUN ["yum", "install", "-y", "nginx"]

# Apache httpd 실행
ENTRYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"]


이 Dockerfile을 기반으로 다음 커맨드를 통해 이미지를 생성해봅시다.

docker build -t sample-entrypoint .

docker run -d -p 82:80 sample-entrypoint /usr/sbin/nginx -g "daemon off;"

앞서 Dockerfile에서 ENTRYPOINT 명령으로 httpd가 실행되도록 입력했으므로 브라우저에서 82번 포트로 액세스 시, nginx가 실행되지 않는 것을 확인할 수 있습니다.

한편, Dockerfile에 ENTRYPOINT 명령이 여러 개 입력되어 있는 경우에는 가장 마지막 명령어가 실행됩니다.


build 완료 후에 실행되는 명령(ONBUILD)

ONBUILD는 이미지 내의 다음 build에서 실행되는 커맨드를 설정하는 명령입니다.

생성된 이미지를 다른 Dockerfile에서 베이스 이미지로 설정하여 build하면, ONBUILD의 커맨드가 실행됩니다.

ONBUILD [실행하고자 하는 커맨드]

웹 애플리케이션의 실행 환경을 구축할 때 이 ONBUILD 명령을 사용하는 경우가 많습니다.

예를 들에 웹 시스템을 구축할 때 OS 설치 및 환경 설정, 웹 서버 및 각종 라이브러리 설치 등 인프라 환경을 구축하기 위해 베이스 이미지를 생성합니다. 이때, ONBUILD 명령으로 이미지 내에 심어진 프로그램을 deploy하는 명령(ADD나 COPY 등)을 입력합니다.

이처럼, 인프라 생성은 인프라 구축에 관련된 것과 애플리케이션 deploy에 관련된 것으로 나눌 수 있습니다.

또한, docker inspect 명령으로 이미지에 ONBUILD 명령이 설정되어 있는지의 여부를 확인할 수 있습니다.

docker inspect --format="{{ .Config.Onbuild }}" <이미지명>


4-3 환경 및 네트워크 설정

환경 변수 설정(ENV)

Dockerfile 내에서 환경변수를 설정하고자 할 때에 사용합니다. ENV 명령을 실행하는 방법에는 다음과 같은 몇 가지가 있습니다.

key value 형식으로 설정

ENV [key] [값]
  • 하나의 환경 변수에 하나의 값을 설정
  • key 다음에 입력된 문자열을 하나의 값으로 인식
  • 공백이나 " " 등과 같은 character 값도 모두 문자로 인식
  • 명령어마다 Docker 이미지가 생성

key=value 형식으로 설정

ENV [key]=[값]
  • 한 번에 여러 개의 값을 설정
  • 값에 공백이 포함될 때에는 " "나 \를 사용
  • 하나의 Docker 이미지가 생성

변수 앞에 \을 붙이면 환경 변수를 escape할 수 있습니다.

단, ENV 명령으로 설정한 환경 변수는 컨테이너 실행 시 docker run 커맨드의 env 옵션을 사용해 변경할 수 있습니다.


작업 디렉터리 설정(WORKDIR)

Dockerfile에서 저장한 명령(RUN, CMD, ENTRYPOINT, COPY, ADD)을 실행하는 작업 디렉터리 설정

WORKDIR [작업 디렉터리 경로]

Dockerfile에서 여러 번 사용할 수 있으며 작업 디렉터리의 경로를 상대 경로로 설정하면 이전 WORKDIR 명령의 경로를 기준으로 한 상대 경로로 설정됩니다.

WORKDIR 명령에 ENV로 설정한 환경 변수를 사용할 수도 있습니다.


사용자 설정(USER)

이미지 실행 또는 Dockerfile 내의 RUN, CMD, ENTRYPOINT 명령어를 실행시킬 사용자를 설정

USER [사용자명/UID]

USER로 사용자를 설정하기 위해서는 RUN 명령에서 미리 사용자를 추가해놓아야 합니다.


라벨 설정(LABEL)

버전, 커맨드 등의 정보를 이미지에 심을 때 사용

LABEL key=

공백을 포함시킬 때에는 " ", 행갈이가 필요할 때에는 \을 사용합니다.


포트 설정(EXPOSE)

컨테이너에 공개할 포트 번호를 설정

EXPOSE <포트 번호>

EXPOSE 명령을 통해 Docker에서 실행 중인 컨테이너가 listen하고 있는 네트워크 포트를 알 수 있습니다. Docker는 이를 통해 링크 기능으로 컨테이너와 내부를 연결합니다. 또한 docker run 명령에서 p 옵션을 사용할 때, 호스트에 어떤 포트를 공개할지 정의합니다.


4-4 파일 시스템 설정

파일 및 디렉터리 추가(ADD)

이미지에 호스트의 파일과 디렉터리를 추가할 때 사용

ADD <호스트 파일 경로> <Docker 이미지 파일 경로>
ADD ["호스트 파일 경로" "Docker 이미지 파일 경로"]

ADD 명령은 호스트의 파일 및 디렉터리, 원격 파일을 Docker 이미지의 파일 시스템에 복사합니다.

Docker 이미지의 파일 시스템은 절대 경로 또는 WORKDIR 명령에서 지정한 디렉터리를 기점으로 지정합니다.

이미지에 추가하고자 하는 파일이 원격 파일 URL인 경우, 추가한 파일은 600(사용자만 입력 및 출력 가능) 퍼미션을 가집니다.

또한 ADD 명령은 인증을 지원하지 않기 때문에 원격 파일 다운로드 시 인증이 필요한 경우, RUN 명령에서 wget 커맨드나 curl 명령을 사용하면 됩니다.


파일 복사(COPY)

이미지에 호스트의 파일이나 디렉터리를 복사할 때 사용

COPY <호스트 파일 경로> <Docker 이미지 파일 경로>
COPY ["호스트 파일 경로" "Docker 이미지 파일 경로"]

COPY는 ADD와 비슷합니다. ADD 명령은 원격 파일을 다운로드하거나 파일 압축풀기 등이 가능하지만 COPY 명령은 호스트의 파일을 이미지 내의 파일 시스템에 복사하는 작업만 수행합니다. 그러므로 단순하게 이미지에 파일을 복사하고 싶을 때에는 COPY 명령을 사용해야 합니다.


볼륨 마운트(VOLUME)

이미지에 볼륨을 할당할 때 사용

VOLUME ["/마운트 포인트"]

VOLUME으로 마운트 포인트를 생성하고 호스트와 다른 컨테이너에서 볼륨을 외부 마운트합니다.

볼륨은 하드웨어의 기억장치를 의미하고, 마운트란 기억장치와 주변기기를 OS에 인식시켜 사용 가능한 상태로 만드는 것을 의미합니다.


반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함