FROM
- docker 컨테이너를 어떤 docker 이미지로부터 생성할지 기술.
- 이것을 베이스 이미지라고 한다.
- 이 명령은 필수 명령 항목이다.
- 태그를 생략하면 베이스 이미지의 최신 버전이 적용된다.
- 고유한 이미지를 특정해서 명시하려면 다이제스트를 사용한다.
Ex)
FROM [이미지명]
FROM [이미지명]:[태그명]
FROM [이미지명]@[다이제스트]
FROM centos:centos7
FROM tensorflow/tensorflow@sha256:27394k393.....
* digest 값이란?
도커 허브에 이미지를 업로드하면 자동으로 부여되는 unique한 식별자.
이 값은 고유하므로 특정 이미지를 지정할 때 사용할 수 있다.
다이제스트 값을 확인하려면 다음 명령을 사용한다.
#docker image ls --digests [이미지명]
LABEL
Dockerfile로 생성할 이미지에 버전 정보나 작성자 정보, 코멘트 등을 제공하는 데 사용한다.
Ex)
구문 : LABEL <키 명>=<값>
도커 파일에 아래와 같이 명시할 수 있다.
LABEL maintainer="sungsikyung<ssking@live.or.kr>"
LABEL title="webapp"
LABEL version="10.1"
LABEL description="This test images thanks"
빌드 후, docker image inspect로 확인 --> docker image inspect --format="{{ .Config.Labels }}" 이미지명
map[description:This test images thanks maintainer:admin<admin@live.or.kr title:webapp version:10.1]
SHELL
쉘 형식으로 명령을 실행할 때의 기본 쉘을 설정한다.
SHELL 명령을 지정하지 않았을 때 리눅스의 기본 쉘은 /bin/bash -c 이며, 윈도우는 cmd /S /C 이다.
SHELL 명령을 지정하면, 그 쉘은 그 이후에 도커파일 안에서 쉘 형식으로 지정한 RUN, CMD, ENTRYPOINT 명령에서 유효해진다.
Ex)
구문 : SHELL ["쉘의 경로", "파라미터"]
SHELL ["/bin/bash", "-c"]
RUN echo hello
WORKDIR
- 작업 디렉토리를 지정한다.
- 즉 도커 파일에서 정의한 명령을 실행하기 위한 기본 디렉토리를 지정한다.
- 대상이 되는 명령은 다음과 같다.
- (RUN, CMD, ENTRYPOINT, COPY, ADD) 또한, WORKDIR 명령에서 지정한 디렉토리가 존재하지 않는다면 알아서 새로 만드므로 따로 미리 만들어 둘 필요는 없다.
- 이 명령은 도커 파일 안에서 여러 번 사용할 수 있다.
- 필요에 기본디렉토리를 바꿔가며 dockerfile 내용을 전개할 수 있다.
- 만약 상대 경로를 지정한 경우는 이전 WORKDIR 명령의 경로에 대한 상대 경로가 된다.
- 추가로, WORKDIR 명령에는 ENV 명령에서 지정한 환경변수를 사용할 수 있다.
Ex)
ENV로 지정한 환경변수를 사용하기
ENV DIRPATH /first
ENV DIRNAME second
WORKDIR $DIRPATH/$DIRNAME
RUN ["pwd"]
결과 : /first/second
USER
- 이미지 실행이나 도커 파일의 RUN, CMD, ENTRYPOINT 명령을 실행하기 위한 사용자를 지정한다.
- USER 명령에서 지정하는 사용자는 RUN 명령으로 미리 만들어 두어야 한다.
- 구문은 다음과 같다 : USER [사용자명/UID]
RUN ["whoami"] // 현재 root가 현재 유저
RUN ["adduser", "test1"] // 유저를 생성
USER test1 // 해당 유저로 로그인한다.
RUN ["whoami"] // test1 유저 상태를 확인할 수 있다.
ENV
- 도커 파일 안에서 환경변수를 설정한다.
- ENV 명령으로 지정한 환경변수는 컨테이너 실행 시의 docker container run 명령의 --env 옵션을 사용하면 변경할 수 있다.
- 구문 key value 형식과 key=value 형식 2가지가 있다.
- key value 형으로 지정하는 경우, 단일 환경변수에 하나의 값을 지정한다.
- 첫 번째 공백 앞을 key로 설정하면 그 이후는 모두 문자열로서 취급한다.
- 공백이나 따옴표와 같은 문자를 포함한 것도 문자로 취급한다.
- 이 명령을 실행하면 명령 별로 도커 이미지를 만든다.
- 아래 예시는 ENV가 3줄이므로 3개의 도커 이미지가 생긴다.
Ex)
구문 : ENV [key] [value]
ENV myName "Gidong Hong"
ENV myOrder admin client
ENV myNickName GDH
key=value 형으로 지정하는 경우, 한 번에 여러 개의 값을 설정할 때는 이 방식을 사용한다.
아래 예시처럼 ENV 후 한 줄에 싹 다 쓸 수 있다.
이렇게 한줄에 하면 만들어지는 도커 이미지는 하나이다.
또한 변수 앞에 \를 추가하면 이스케이프 처리를 할 수 있다.
예를 들어 \$myName은 $myName이라는 리터럴로 치환할 수 있다.
Ex)
구문 : ENV [key] = [value]
ENV myName="Gildong Hong"/
myOrder=admin client/
myNickName GDH
ARG
도커 파일 안에서 사용할 변수를 정의한다.
이 명령을 사용하여 변수의 값에 따라 생성되는 이미지의 내용을 바꿀 수 있다.
환경변수 ENV와 달리 이 변수는 도커파일 안에서만 사용할 수 있다.
또한, 해당 도커 파일을 빌드할 때, --build-arg 옵션을 사용하여, 도커파일 내부에 정의된 변수에 기본값을 넣을 수 있다.
Ex)
구문 : ARG 이름 [=기본값]
ARG YOURNAME="test1"
RUN echo $YOURNAME
예시대로 도커 파일을 구성하고 빌드할 때 아무 옵션 없이 한다면 그대로 test1이 정의되겠지만, 아래와 같이 --build-arg 옵션을 사용하여 변수를 바꿀 수 있다.
원래 test1이었으나 younghee로 바뀐다.
#docker build. --build-arg YOURNAME=younghee
RUN, CMD, ENTRYPOINT 이란?
- 이 세 명령어는 모두 명령을 실행하는 역할을 한다.
- 하지만 각기 특성이 있고 차이가 있어 함께 설명해야 이해가 빠르므로, 3개를 비교하여 함께 설명한다.
- 기본적으로 RUN은 이미지 작성, 즉 컨테이너 자체에 적용된 명령이며,
- CMD와 ENDPOINT는 만들어진 이미지를 바탕으로 생성된 컨테이너 위에서 실행하는 명령이라고 이해할 수 있다.
- 예를 들어, 웹서버를 가동하기 위해 nginx를 설치하는 것은 RUN으로 하지만, 설치한 nginx를 데몬으로서 컨테이너 안에서 작동시키려면 CMD를 사용한다.
- 세 명령어 모두 실행 방식 2가지를 가진다. shell 커맨드 방식, EXEC 방식 두 가지이다.
1. 쉘 커맨드 방식
- 내부적으로 shell 명령어를 호출(/bin/sh -c <command>)하여(/bin/sh -c "명령어" 는 그냥 쉘에서 명령어 치는 거랑 동일한 효과이다), 사용자가 지정한 command를 호출한다.
- 즉 쉘을 한번 통해야 한다.
구문 :
RUN command
CMD command param1 param2
ENTRYPOINT command param1 param2
Ex)
RUN apt-get install -y nginx
CMD echo "This is a test."
ENTRYPOINT echo $HOME
2. EXEC 방식
- shell방식처럼 내부적인 변환이 아니라, 사용자가 명확하게 실행파일을 명시하여 실행할 수 있다.
- 쉘을 통하지 않는다.
- 꼭 EXEC 형식이 필요한 경우는 /bin/bash가 없는 컨테이너인 경우, 다른 쉘을 이용하고 싶은 경우 RUN 명령에 쉘의 경로를 지정하는 방식으로 EXEC를 사용할 수 있다.
- EXEC 형식에서는 실행할 명령을 JSON 배열로 지정한다.
- 또한 값에 문자열을 입력할 때는 싱글 쿼테이션을 쓴다.
- SHELL 방식보다 EXEC 방식이 권고된다.
구문
RUN ["executable", "param1", "param2"]
CMD [“executable”,”param1”,”param2”]
CMD [“param1”,”param2”] (ENTRYPOINT 인수 형식. 실행되는 명령은 없고 ENTRYPOINT가 실행될 때 파라미터 전달)
ENTRYPOINT [“executable”, “param1”, “param2”]
Ex)
RUN ["apt-get", "install", "python3"]
RUN ["/bin/bash", "-c", "apt-get install -y nginx"]
RUN ["echo", "hello. this is jacob"]
CMD ["/bin/echo", "Hello world"]
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/echo", "Hello world"]
ENTRYPOINT ["nginx", "-g", "daemon off;"]
※ EXEC 방식에서 쉘 변수 사용
- ENTRYPOINT ["/bin/echo", "Hello, $name"] 는 결과가 Hello, $name 이라고 나온다.
- EXEC 방식은 쉘을 통과하지 않으므로 쉘 변수를 읽을 수 없기 때문이다.
- 다음과 같이 쉘을 실행시키고 echo 명령을 수행하도록 하면 제대로 작동한다.
Command
FROM ubuntu:latest
ENV name Nasdaq
["/bin/bash", "-c", "echo Hello, $name"]
※ CMD, ENTRYPOINT, RUN 을 어떻게 쓰는지 간단하게 정리하면 다음과 같다.
RUN : 패키지를 설치할 때
CMD : 컨테이너 실행 시점/환경에 따라 명령어를 다양하게 지정해야 하는 경우
ENTRYPINT : 컨테이너 실행 시 항상 수행해야 하는 명령어 지정. 웹서버, DB 등 프로세스가 항상 구동되어야 할 때 등.
관련하여 더욱더 자세한 내용은 다음 링크를 참고한다.
docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact
Ctil + F = Dockerfile reference
아래 내용서부터
Dockerfile reference
Estimated reading time: 81 minutes
Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image
RUN
- RUNFROM 명령에서 지정한 베이스 이미지에 대해 새로운 레이어에서 (즉 이미지가 생성됨) 명령어를 실행한다.
- 패키지 설치, 미들웨어 설정, 환경 구축 등을 위한 명령을 실행하는 데 많이 사용된다.
- 도커 파일 내에 기술된 순서에 따라 순차적으로 실행하므로 도커 이미지 실행 시 명령어 한 줄씩 실행되는 로그를 확인할 수 있다.
- RUN 명령의 개수는 제한이 없다.
※ 주의사항
- RUN에 명령어를 입력할 때 서로 관계있는 명령어는 &&를 사용하여 한 레이어에 수행해야 한다.
- 예를 들어, 예시 1보다는 예시 2대로 수행해야 한다.
- 각 명령은 레이어별로 이미지가 생기므로, 예시 1의 마지막 줄 RUN은 apt-get update가 적용되지 않는다.
Ex1)
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y curl
Ex2)
FROM ubuntu:14.04
RUNapt-get update && apt-get install -y curl
※ 명령 줄 바꿈
- RUN 명령 실행 시 \으로 줄 바꿈이 가능하다.
- 가독성을 위해 사용된다.
Command
RUN yum -y install\
httpd\
php
CMD
- 컨테이너 실행 시 default로 실행되는 명령이나 파라미터를 설정한다.
- docker container run 실행 시 따로 명령어를 명시하지 않으면, CMD에 명시된 명령이 default로 실행된다.
- 만약 따로 명령어를 명시한다면, CMD로 기술한 내용은 무시되고, 실행 시 명시한 명령어가 작동된다.
- 또한 ENTRYPOINT 명령의 파라미터를 설정하는 역할도 수행한다.
- dockerfile에는 하나의 CMD를 기술할 수 있다.
- 만일 여러 개를 쓴다면 마지막 명령만 유효하다.
ENTRYPOINT
- CMD는 docker container run 실행 시 따로 명령어가 명시된다면 해당 명령어로 대체되지만, ENTRYPOINT는 컨테이너 실행 시 반드시 실행 명령에 포함된다.
- 또한 컨테이너 실행 시 따로 명령어를 명시하는 경우, ENTRYPOINT와 명령어가 동일하다면 옵션만 명시한 명령어대로 적용되고, 명령어가 다르다면 ENTRYPOINT의 내용과 컨테이너 실행 시 명시한 내용이 한 줄에 다 쓰는 것처럼 되어 에러가 난다.
- 예를 들어, 엔드포인트가 ls -artl 이고 컨테이너 실행 시 명령을 ls -al 로하면 ls -al로 실행되지만, 컨테이너 실행시 df -h 로 했다면 실제 명령이 ls -artl df -h 가 되어 에러가 나는 것이다.
- 추가로, container run 시 --entrypoint="실행명령" 옵션을 사용하여 dockerfile에 정의한 ENTRYPOINT를 변경할 수 있다.
- ENTRYPOINT ["/bin/bash", "-c", "echo Hello, $name"] 가 포함된 도커 파일을 빌드한 후 컨테이너를 생성할 때 다음과 같이 수행했다면, (docker run --entrypoint="cat" test /etc/hosts) "echo Hello, $name"이 부분은 무시되고 cat /etc/hosts 명령이 실행된다.
- ENTRYPOINT 명령에서 지정한 명령은 반드시 컨테이너에서 실행되는데, 실행 시 명령 인수를 지정하고 싶을 때 CMD와 함께 조합하여 사용되기도 한다.
- 예를 들어, ENTRYPOINT 명령은 실행하고 싶은 명령 자체, 즉 꼭 실행하는 명령을 지정하고, CMD 명령은 ENTRYPOINT로 실행된 명령의 인수를 지정하면 컨테이너 실행 시 디폴트 작동을 결정할 수 있다.
※ ENTRYPOINT와 CMD를 함께 사용하기
Ex1) 아무 인수 없이 docker container run 했을 때, "Hello world"가 출력된다. 만약 docker container run 할 때 인수를 주면, "Hello 인수"가 출력된다.
Command
FROM ubuntu
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
Ex2) 명령 없이 그대로 컨테이너를 실행하면, top -d 10 이 실행된다. docker container run -it sample -d 2 이렇게 실행하면, top -d 2 가 실행된다.
Command
FROM ubuntu:16.04
ENTRYPOINT ["top"]
CMD ["-d", "10"]
STOPSIGNAL
- docker container stop을 실행하면 도커 데몬은 컨테이너에게 signal을 보내서 중지시킨다.
- 기본적으로는 SIGTERM을 사용한다. (SIGTERM은 15이고, SIGKILL은 9이다) STOPSIGNAL은 이러한 컨테이너 종료 시그널을 변경할 수 있다.
- 크게 사용되지는 않는다.
구문
STOPSIGNAL [시그널 번호 또는 이름]
Ex)
STOPSIGNAL SIGKILL
EXPOSE
- 컨테이너의 공개 포트번호를 지정한다.
- 이 명령은 도커에게 실행 중인 컨테이너가 LISTEN 하고 있는 네트워크를 알려준다.
- 이 명령 자체가 작성된 포트를 실행하여 리스닝시키는 것이 아니므로, 실제로 포트를 열려면 컨테이너 시작 시 -p 또는 -P 옵션을 사용해야 한다.
구문
EXPOSE 포트넘버/프로토콜 (프로토콜을 지정하지 않으면 기본값은 tcp)
Ex)
EXPOSE 8080/tcp (8080 TCP 포트를 공개)
HEALTHCHECK
- 컨테이너 안의 프로세스가 정상적으로 작동하고 있는지 체크하는 구문을 추가한다.
- 이러한 체크는 체크 간격, 체크 타임아웃 시간, 타임아웃 회수 등으로 해당 컨테이너의 상태를 체크할 수 있다.
- 헬스체크 결과는 docker container inspect 명령으로 상세하게 확인할 수 있고, 간단하게는 docker container ls 명령으로도 확인할 수 있다.
구문
HEALTHCHECK [옵션] CMD 실행할 명령
옵션
옵션명 | 설명 | 기본값 |
--interval=n | 헬스체크 간견 | 30초 |
--timeout=n | 헬스체크 타임아웃 | 30초 |
--retries=N | 타임아웃 횟수 | 3 |
Ex)
5분마다 가동 중인 웹서버의 메인페이지(http://localhost/)를 3초 안에 표시할 수 있는지 없는지 확인하기 (도커 파일까지 구축하는 상세 예시는 맨 아래 전체 통합 예시 참조)
#HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
* docker container inspect로 상태 확인
"Health": {
"Status": "starting",
"FailingStreak": 0,
"Log": [] }
안되면 아래와 같은 로그들이 남는다.
"Health": {
"Status": "starting",
"FailingStreak": 1,
"Log": [
{
"Start": "2021-04-12T14:30:47.743974318+09:00",
"End": "2021-04-12T14:30:47.872516208+09:00",
"ExitCode": 1,
"Output": "/bin/sh: 1: curl: not found\n"
}
]
여기 보면 curl 명령이 없는 것을 알 수 있다.
직접 들어가서 설치 후, 다시 기다려보자.
ADD
이미지에다가 호스트에 있는 파일이나 디렉토리, 원격 파일을 도커 이미지 안에 추가한다.(복사함)
구문
ADD 호스트파일경로 도커이미지파일경로
Ex)
ADD ["호스트파일경로" "도커이미지파일경로"]
- 호스트 파일 경로에는 와일드카드, GO언어의 filepath.match 룰과 일치하는 패턴을 사용할 수 있다.
- 도커 이미지 안의 파일은 절대 경로로 지정하거나 WORKDIR 명령에서 지정한 디렉토리를 기점으로 상대 경로로 지정한다.
- 호스트의 파일이 TAR 아카이브거나 압축포맷(gzip, bzip2 등)일 때는 디렉토리로 압축을 푼다. 단 원격 URL로 받은 것은 압축이 풀리지 않는다.
※ 원격 파일을 받는 경우
- 이미지에 추가할 파일이 원격파일 URL일 경우, 추가한 파일은 퍼미션이 600이 되며, 만일 취득한 원격 파일이 HTTP Last-Modified 헤더를 갖고 있다면 추가된 파일에서 mtime 의 값으로 사용된다.
- 원격 파일 URL을 받을 경우, 인증을 지원하지 않으므로 원격 파일의 다운로드에 인증이 필요한 경우 RUN 명령에서 wget이나 curl 명령을 사용해야 한다.
- 또한 이미지 안의 파일 지정이 파일(마지막이 슬래시가 아님) 일 때는 URL로부터 파일을 다운로드하여 지정한 파일명을 추가한다.
- 이미지 안의 파일 지정이 디렉토리(마지막이 슬래시) 일 때는 파일명은 URL로 지정한 것이 된다.
Ex)
호스트상의 host.html을 이미지 안에 /docker_dir/ 에 추가
ADD host.html /docker_dir/
hos로 시작하는 모든 파일 추가
ADD hos* /docker_dir/
[hos]+ 임의의 한 문자 룰에 해당하는 파일 추가
ADD hos?.txt /docker_dir/
원격 파일 추가
ADD http://www.wings.msn.to/index.php /docker_dir/web/
COPY
- 이미지에 호스트상의 파일이나 디렉토리를 복사한다.
- ADD명령과매우 비슷한데, ADD는 원격 파일의 다운로드나 아카이브의 압축해제 등의 기능이 있지만 COPY는 단순히 "복사"만 한다.
- 따라서 단순히 이미지 안에 파일을 넣고 싶을 때는 COPY를 사용한다.
구문
COPY 호스트파일경로 도커이미지파일경로
COPY ["호스트파일경로" "도커이미지파일경로"]
Ex)
COPY /test/index.html /usr/share/nginx/html/index.html
이렇게 하면, 호스트의 /test/index.html 파일을 usr/share/nginx/html/index.html로 넣는다.
VOLUME
- 이미지에 볼륨을 할당한다.
- 지정한 이름의 마운트 포인트를 작성하며, 기본적으로 아래 링크에서 "호스트 디스크를 명시하지 않고 생성" 하는 방식으로 생성된다.
- 해당 링크 참고할 것.
2020/06/13 - [Category] - [Docker Basic] 16. Dockerfile을 이용하여 이미지 빌드하기
구문 : VOLUME ["/마운트포인트"]
예시도 위 링크를 참고하면 된다.
ONBUILD
- 그다음 빌드에서 실행할 명령을 이미지 안에 설정하는 명령.
- 즉, 자신의 도커 파일로부터 생성한 이미지를 베이스로 이미지로 한, 다른 도커 파일을 빌드할 때 실행하고 싶은 명령을 기술하는 것이다.
- 예를 들어, 최초 도커 파일에서 ONBUILD RUN echo "HELLO"를 기술했다면, 해당 도커 파일을 빌드했을 때는 아무 일도 없지만, 빌드된 이미지를 갖고 누군가가 이미지를 새로 만들면 HELLO가 출력되게 된다.
- 한마디로 명령의 실행 타이밍을 늦출 수 있는 것.
- 주요 실무 사용으로는, 예를 들어 웹 시스템 구축 시 os설치 및 환경설정, 웹서버 설치, 각종 플로그인 설치 등의 인프라 환경 구축 부분을 베이스 이미지로 만들고, 그 안에 onbuild 명령으로 이미지 안에 개발한 프로그램을 전개하는 명령 ADD나 COPY 등을 지정한다.
- 이렇게 하면, 최초 이미지는 인프라만 지정되어 있고, 그다음 개발자가 해당 이미지를 갖고 애플리케이션 구축 부분을 코딩하고 아까 만든 베이스 이미지를 바탕으로 한 이미지를 작성한다.
- 이 이미지 안에는 프로그래밍이 끝난 업무 애플리케이션이 전개된다.
- 즉 "인프라 구축"과 "애플리케이션 전개"의 업무를 분할하는 것이다.
- 실제로 사용되는 예시로는, 웹서버용 이미지를 최초 빌드하는 사람이, 웹서버를 실행하는 것은 그 이미지를 기반으로 다시 이미지를 만드는 사람들을 위해 지연시키고, 다른 환경만 세팅해서 최초 이미지를 만들고, 이후 그걸 가지고 여럿이 웹서버 개발을 수행할 때는 ONBUILD에 있는 웹서버 실행 구문이 실행되게 하는 식으로 사용할 수 있다.
※ 개발 흐름의 이해
- 애플리케이션 개발 현장에서 한 명이 모든 것을 개발하는 일은 드물다.
- 여럿이 협업해서 진행하는 경우가 많다. 팀 멤버가 각각 도커 파일을 작성하고 그걸로 이미지를 작성한다면 도커를 써도 어플리케이션 실행환경이 제각각이 될 수 있다.
- 그래서, 개발팀 안에 도커파일 작성 담당자를 정하고, 그 담당자가 OS/미들웨어의 설치나 설정, 라이브러리의 검증/도입을 수행하고 베이스가 되는 도커파일을 만든다.
- 다른 개발자들은 이 베이스 도커파일을 바탕으로 각자 개발한 소스코드를 전개하여 테스트를 하면, 팀 멤버 전원이 동일한 실행 환경에서 개발과 테스트를 할 수 있다.
- 베이스 도커파일을 생성하는 사람은 인프라와 애플리케이션 모두 정통한 엔지니어가 적임이다.
- 아무튼, 팀 개발을 할 때는 개발환경의 베이스 도커 파일을 바탕으로 만든 이미지를 공유하여 작업을 수행해야 한다.
- 또한 도커 파일은 GIT 등을 사용하여 팀 내에서 공유하고 버전을 관리할 수 있다.
'IT Technology > Cloud' 카테고리의 다른 글
Docker 기본 명령어 (정보확인, 관리) (0) | 2021.05.01 |
---|---|
도커 이미지란? Docker image ? (0) | 2021.04.22 |
Dockerfile 이용하여 이미지 빌드하기 (0) | 2021.04.15 |
Docker 단독 컨테이너 실행 실습하기 (0) | 2021.04.13 |
Docker 중요 명령어 (docker run) 운영체제, 소프트웨어 컨테이너 (0) | 2021.04.12 |