본문 바로가기

OpenSource/Docker

[Docker] Dockerfile을 이용한 도커 이미지 선언하기

도커 이미지를 여러번 만들어 사용해보았지만, 기존에 만들어진, 혹은 github에 공유된 Dockerfile을 기준으로 복사하고 짜집기 하여 사용해왔었다. 오늘은 Dockerfile Format에 대해 정리해보려고 한다.

1. 주석

도커파일 내 주석은 아래와 같이 표현한다.

# Comment

2. FROM

새로 생성하고자 하는 이미지의 베이스 이미지를 선언한다

FROM 이미지명            # 태그를 선언하지 않을 경우 latest 태그가 적용된다.
FROM 이미지명:태그명     # 예시: FROM ubuntu:21.04

3. RUN

베이스 이미지에 명령을 실행하여 어플리케이션을 추가로 설치한다거나 할 때 사용한다.

RUN 명령어

# 예시
## shell 형식으로 실행
RUN apt-get install -y htop
## exec 형식으로 실행
## 아래의 방식은 shell을 통하여 실행되는것이 아니기 때문에 $HOME과 같은 환경변수를 지정할 수 없다.
RUN ["echo", "$HOME"]     ## 실패
RUN ["/bin/bash", "-c", "echo hello"]

## 여러 명령을 한번에 수행하려면 \를 이용하여 선언한다
RUN yum -y install \
           nginx \
           php

4. CMD

RUN은 베이스 이미지에서 새로운 이미지를 생성하기 위해 실행하는 반면, CMD는 생성된 이미지의 컨테이너 안에서 실행할 명령을 선언한다. Dockerfile 이내에 하나의 CMD만 선언 가능하며, 여러개의 CMD가 존재지 마지막 CMD만 수행된다.

CMD "실행하고자 하는 명령어"

# 예시
## RUN과 마찬가지로 Shell 형식과 exec 형식으로 실행 가능하다

## shell 형식으로 실행
CMD echo $HOME

## exec 형식으로 실행
## RUN과 마찬가지로 shell을 통하여 실행되는것이 아니기 때문에 $HOME과 같은 환경변수를 지정할 수 없다.
CMD ["echo", "$HOME"]     ## 실패
CMD ["/bin/bash", "-c", "echo hello"]

5. ENTRYPOINT

도커 이미지 생성 후 컨테이너 시작시 실행할 명령어를 선언한다. ENTRYPOINT는 Dockerfile 내 하나만 선언 가능하고 중복 선언시 마지막 ENTRYPOINT만 수행된다. 또한 RUN, CMD 커맨드와 동일하게 shell형식, exec 형식으로 실행가능하다.

ENTRYPOINT "실행하고자 하는 명령어"

# 예시
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

ENTRYPOINT 이후에 나오는 CMD는 ENTRYPOINT 실행시 파라미터 전달 역할을 한다.

6. EXPOSE

컨테이너 외부로 노출하고자 하는 포트를 선언한다.
예를 들어 nginx 컨테이너 같은 경우 컨테이너 안의 nginx와 외부 포트와의 연결을 하기 위해 외부로 nginx 의 80포트를 노출해야한다.

EXPOSE 포트번호

# 예시
EXPOSE 80

# 컨테이너 생성시 10000포트를 컨테이너의 80 포트와 매핑하여 컨테이너아이피:10000 으로 컨테이너에 접근 가능하다.
docker run -p 10000:80

7. ENV

컨테이너 내부에서 사용할 환경변수를 설정한다.

ENV "key=value"

# 예시
ENV HTTP_PROXY="http://xxx.xxx.xxx.xxx:3001"
ENV HTTPS_PROXY="http://xxx.xxx.xxx.xxx:3001"

8. ARG

Dockerfile 내에서 사용할 변수를 선언할때 사용한다. ENV를 통해 생성된 환경변수는 컨테이너 내부에서 사용하는 반면, ARG로 선언된 변수는 Dockerfile 내에서만 사용가능하다.

ARG "key=value"

# 예시
ARG SPARK_VERSION=2.4.7
ADD https://www.apache.org/dyn/closer.lua/spark/spark-$SPARK_VERSION/spark-SPARK_VERSION-bin-hadoop2.7.tgz /opt

9. WORKDIR

RUN, CMD, ENTRYPOINT, COPY와 같은 명령어들이 수행될 컨테이너 안의 디렉터리위치를 지정한다.

WORKDIR "/컨테이너 안의 경로"

# 예시
WORKDIR /etc
RUN pwd

9. USER

RUN, CMD, ENTRYPOINT와 같은 커맨드를 수행할 유저를 변경한다. 기본적으로 USER를 통해 사용자를 변경하지 않는다면 root 계정으로 실행된다. 그리고 USER명령어를 사용전에 먼저 사용자가 생성이 되어있어야 함을 잊지말자.

USER 사용자명:그룹

# 예시
RUN ["adduser", "test"]
USER test

10. LABEL

이미지의 버전정보나 작성자 정보 및 코멘트를 등록할때 사용한다.

LABEL 키=값

# 예시
LABEL title="Sample App"
LABEL version="1.0.0"

11. ADD

이미지에 파일이나 디렉토리를 추가할때 사용한다.

## 예시 호스트에 있는 index.html 파일을 컨테이너 안의 /webapp 디렉토리로 복사
ADD index.html /webapp/
## 외부 내트웍의 데이터도 추가 가능하다.
ADD https://www.apache.org/dyn/closer.lua/spark/spark-2.4.7/spark-2.4.7-bin-hadoop2.7.tgz /opt
## 패턴을 이용한 파일도 추가 가능하다.
ADD *.html /webapp/

12. COPY

ADD 와 비슷하게 호스트에 파일을 이미지 안에 복사하기 위해 사용하지만, ADD와 같이 http의 파일을 다운로드 하거나하는 기능은 없고 단순히 호스트 파일을 컨테이너로 복사할때 사용한다.

# 예시
COPY index.html /webapp/
COPY ["index.html", "/webapp/"]

13. VOLUME

컨테이너의 디렉토리를 호스트의 특정위치로 마운트 할수 있게 해준다. 컨테이너 안의 데이터는 컨테이너 삭제시 함께 사라지게 되는데 VOLUME을 통해 컨테이너의 경로를 호스트에 마운트 해 놓으면 컨테이너 삭제시에도 볼륨 마운트한 파일은 삭제되지 않는다.

VOLUME ["/마운트포인트"]
VOLUME /마운트/포인트1 /마운트/포인트2         ## 여러개의 마운트 지점 선언

# 예시
VOLUME /conf

## 호스트와 컨테이너의 볼륨을 마운트
## 컨테이너의 /conf 디렉토리를 호스트의 /host/conf 디렉토리로 마운트  
## 컨테이너 삭제시에도 /host/conf 에 설정 파일인 남아있음
docker run -v /host/conf:/conf ... 생략 ...