DEV ℧ Developer Diary

[Docker] Dockerfile의 작성 방법에 대해 알아보자.

해당 포스트는 inflearn에서 subicura님의 초보를 위한 도커 안내서의 강의를 듣고 정리한 문서입니다.

저번 포스트에는 commit하는 방법을 통해 새로운 이미지를 생성했다.

이번 포스트에는 Dockerfile을 만들어보고, build를 이용해 이미지를 생성해 보고자 한다.

Dockerfile

Dockerfile이란?

Dockerfile은 Docker의 이미지를 생성하기 위한 스크립트이다.

Dockerfile을 작성하면 작성된 한 줄이 하나의 명령어를 뜻하며, 빌드하면 내부 스크립트들을 한 줄 한 줄 해석하며 실행한다.

Dockerfile의 명령어는 대소문자를 구분하지는 않지만 보통 쉘스크립트에서 동작하는 명령어와 구분짓기 위해 일반적으로 대문자로 표기한다.

Dockerfile 장점

Dockerfile은 다음과 같은 장점이 있다.

  • 이미지가 어떻게 만들어져있는지 작성되어 있기 때문에 이미지 생성에 대한 이력을 조회할 수 있다.
  • 패키지 설치, 환경변수 설정, 파일변경 등 다양한 작업을 하나하나 컨테이너를 만들어 작업할 필요 없이 스크립트 하나로 처리가 가능하다.
  • 형상관리 같은 툴을 이용해 타인에게 공유가 용이하다.

Dockerfile 명령어

Dockerfile을 작성하는대는 아래와 같은 명령어를 통해 스크립트를 작성한다.

명령어 description
FROM 기본 이미지
RUN 쉘 명령어를 실행한다.
CMD 컨테이너 기본 실행 명렁어 (Entrypoint의 인자로 사용)
EXPOSE 오픈되는 포트정보
ENV 환경변수 설정
ADD 파일 또는 디렉토리 추가. URL/ZIP 사용 가능
COPY 파일 또는 디렉토리 추가
ENTRYPOINT 컨테이너 기본 실행 명령어
VOLUME 외부 마운트 포인트 생성
USER RUN, CMD, ENTRYPOINT를 실행하는 사용자
WORKDIR 작업 디렉토리 설정
ARGS 빌드타임 환경변수 설정
LABEL Key - value 데이터
ONBUILD 다른 빌드의 베이스로 사용될때 사용하는 명령어

FROM

명령어 FROM은 새 빌드 단계를 초기화 하고 후속 명령을 위해 기본 이미지를 설정한다.

FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

RUN

명령어 RUN은 쉘형식과 exec 형식 두가지 형식이 있다.

RUN <command> # 쉘형식
RUN ["executable", "param1", "param2"] # exec 형식

명령 RUN은 현재 이미지 위에 있는 새 레이어에서 모든 명령을 실행하고 결과를 커밋한다. 커밋된 결과 이미지는 Dockerfile의 다음단계에서 사용된다.

CMD

명령 CMD 에는 세가지 방식이 있다.

CMD command param1 param2 # 쉘 형식
CMD ["param1","param2"] # ENTRYPOINT에 대한 기본 매개변수
CMD ["executable","param1","param2"] # exec 형식, 이것이 선호되는 형식입니다

CMD에는 하나의 명령만 있을 수 있으며, 둘 이상을 나열할 경우 마지막 항목만 CMD명령에 적용된다.

CMD의 목적은 실행중인 컨테이너에 대한 기본값을 제공하는 것인데, 이러한 기본값은 실행 파일을 포함하거나 실행파일을 생략 할 수있다.

exec 형식은 JSON 배열로 구문 분석되므로 작은따옴표(‘)가 아닌 단어 주위에 큰 따옴표 (“)를 사용해야 합니다.

EXPOSE

EXPOSE <port> [<port>/<protocol>...]

명령어 EXPOSE는 컨테이너가 런타임에 지정된 네트워크 포트정보를 Docker에게 알려줍니다.

포트가 TCP 또는 UDP에서 수신하는지 여부를 지정할 수있으며 프로토콜이 지정되지 않은 경우 기본값은 TCP이다.

ENV

ENV <key>=<value> ...

명령어 ENV 는 환경변수를 = 값으로 설정합니다.

명령은 한번에 여러 = 변수를 설정할 수 있도록 허용합니다.

ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
    MY_CAT=fluffy

ADD

ADD에는 두가지 형식이 있습니다.

ADD [--chown=<user>:<group>] [--checksum=<checksum>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

후자의 형식은 공백을 포함하는 경로에 필요합니다.

명령어 ADD는 새 파일, 디렉토리 또는 원격 파일 URL()을 복사하여 경로에 있는 이미지의 파일 경로 () 에 추가합니다.

여러 리소스를 지정할 수 있지만 파일 또는 디렉토리 인경우 해당 경로는 상대경로로 해석된다.

COPY

COPY에는 두가지 형식이 있습니다.

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

후자의 형식은 공백을 포함하는 경로에 필요하다.

명령 COPY<src>의 새로운 파일 경로 디렉토리에서 컨테이너에 있는 <dest>로 파일을 추가한다.

ENTRYPOINT

ENTRYPOINT에는 두가지 방식이 있다.

ENTRYPOINT ["executable", "param1", "param2"] # exec 형식
ENTRYPOINT command param1 param2 # 쉘 형식

둘중에 exec 형식이 선호된다.

명령어 ENTRYPOINT는 컨테이너가 시작되었을 때 스크립트 혹은 명령을 실행하는 역할을 한다.

docker run 명령으로 컨테이너를 생성하거나, docker start 명령으로 정지된 컨테이너를 시작할때 실행된다.

ENTRYPOINT는 Dockerfile에서 단 한번만 사용할 수 있다.

VOLUME

VOLUME ["/data"]

명령어 VOLUME는 빌드된 이미지로 컨테이너를 생성했을 때 호스트와 공유할 컨테이너 내부의 디렉토리를 설정한다.

docker run에서 -v 옵션과 같다.

USER

USER <user>[:<group>]

명령어 USER는 사용자 이름(또는 UID)를 설정한다.

WORKDIR

WORKDIR /path/to/workdir

명령어 WORKDIR는 Dockerfile에서 뒤에 오는 RUN, CMD, ENTRYPOINT, COPYADD 명령어에 대한 작업 디렉터리를 설정합니다. WORKDIR이 존재하지 않으면 후속 Dockerfile 명령에서 사용되지 않더라도 생성된다.

ARG

ARG <name>[=<default value>]

명령어 ARG는 사용자가 --build-arg <varname>=<value> 플래그를 사용하여 docker build 명령으로 빌드 시 빌더에 전달할 수 있는 변수를 정의한다. 사용자가 Dockerfile에 정의되지 않은 빌드 인수를 지정하면 빌드에서 경고를 출력 하게 된다.

LABEL

LABEL <key>=<value> <key>=<value> <key>=<value> ...

명령어 LABEL=한쌍의 이미지 메타데이터를 추가한다.

ONBUILD

ONBUILD <INSTRUCTION>

명령어 ONBUILD는 이미지가 다른 빌드의 기반으로 사용될 때, 나중에 실행할 트리거 명령을 이미지에 추가한다.

더욱 자세한 Dokerfile의 공식 레퍼런스 문서는 아래의 링크에서 확인이 가능하다.

Dockerfile Reference

Dockerfile build

Dockerfile 파일을 생성한다면 아래의 명령어를 통해서 build 할 수 있다.

docker build -t {이미지명:아마자탸구} {빌드 컨텍스트}
  • -f <Dockerfile 위치> 옵션을 사용해 다른 위치의 DOckerfile 파일이 사용 가능하다.
  • -t 명령어로 도커 이미지 이름을 지정한다.
  • {namespace}{image name}:{tag} 형식이다.
  • 마지막에는 빌드 컨텍스트 위치를 지정한다.
    • 현재 디렉토리를 의미하는 점(.)을 주로 사용한다.
    • 필요한 경우 다른 디렉토리를 지정할 수도 있다.

.dockerignore

.gitignore와 비슷한 역할을 한다. 도커빌드 컨텍스트에서 지정된 패턴의 파일을 무시한다.

.git이나 node_module 와 같은 민감한 정보를 제외하는 용도로 주로 사용한다.

.git이나 asset 디렉터리만 제외해도 빌드 속도가 개선된다.

하지만 이미지 빌드시에 사용하는 파일은 제외시키면 안된다.

실습

이제 Dockerfile을 실습해보도록 하자.

Dockerfile을 이용해 이미지를 만들어 보고자 한다, 설치하는 이미지는 저번 포스트와 동일하게 ubuntu 환경에 git을 설치해보고자 한다.

Dockerfile을 생성하고 아래의 명령어를 입력해주자.

FROM ubuntu:latest

RUN apt-get update
RUN apt-get install -y git

Dockerfile 파일을 생성했다면 build 명령어를 통해 이미지를 생성해주자.

git-dockfile이라는 태그를 가진 ubuntu 이미지를 실행시킨다는 명령어이다.

docker build -t ubuntu:git-dockerfile

이후 docker images 명령어를 사용하면 git-dockerfile 태그를 가진 이미지가 생성된걸 확인할 수 있다.

docker images

docker images
REPOSITORY            TAG              IMAGE ID       CREATED              SIZE
ubuntu                git-dockerfile   0f9712ec5bad   About a minute ago   194MB

한번 Dockerfile로 생성한 이미지를 실행시켜 보도록 하자.

이후 git 명령어를 확인하면 실행한 ubuntu에 git이 설치되어 있는것을 확인할 수 있을 것이다.

PS C:\WINDOWS\system32> docker run -it --name git3 ubuntu:git-dockerfile
root@4448d5497681:/# git --version
git version 2.34.1