[도커 기초 시리즈 포스팅]
[Docker] 기초 시리즈 (1) 도커의 개념과 사용이유
[Docker] 기초 시리즈 (2) Ubuntu에 도커 엔진 설치
[Docker] 기초 시리즈 (3) 이미지와 컨테이너 관계, 도커 아키텍처
[Docker] 기초 시리즈 (4) 도커 이미지의 구조
[Docker] 기초 시리즈 (5) 도커 이미지 다루기 - Docker Hub(Registry)
[Docker] 기초 시리즈 (6) 도커 이미지 다루기 - 이미지 직접 생성
[Docker] 기초 시리즈 (7) 자주 사용하는 Dockerfile 명령어 (Now)
[Docker] 기초 시리즈 (8) 자주 사용하는 도커 명령어 모음
[Docker] 기초 시리즈 (9) 도커 컨테이너 - 개념, 기본 사용법
[Docker] 기초 시리즈 (10) 도커 컨테이너 - Volume 관리
❑ 자주 사용하는 Dockerfile 명령어
FROM
FROM <base image>:<tag>
예) FROM ubuntu:20.04
- 베이스 이미지 지정. 반드시 한 번 이상 입력해야 함
WORKDIR
WORKDIR <경로>
예) WORKDIR /app
- WORKDIR를 지정하면 그 이후 명령어는 컨테이너에서 해당 디렉토리를 기준으로 동작한다.
- 일반적으로 절대 경로를 사용하며 상대 경로를 사용하면 가장 마지막으로 입력한 WORKDIR를 기준으로 경로를 추가한다.
- WORKDIR는 도커 파일 내 여러 번 사용할 수 있으며, 지정하지 않을 경우 Default WORKDIR는 ' / ' 로 설정된다.
RUN
1) RUN <전체 명령문>
2) RUN ["<명령문>", "<파라미터1>", "<파라미터2>"]
*일반적으로 RUN <수행 명령문>을 사용한다
예) RUN apt-get update
예) RUN npm install
- 쉘(shell)에서 커맨드를 실행하는 것 처럼 이미지를 빌드하는데 필요한 어플리케이션 또는 패지키를 설치하는데 사용한다.
- RUN 명령어가 실행되면 새로운 이미지 layer를 생성 후 실행하고 커밋한다. 커밋된 이미지는 RUN 이후 Dockerfile에서 이뤄지는 작업에 사용된다.
COPY
COPY source(도커 호스트 OS 파일) dest(이미지 내 위치)
*dest에 상대 경로를 입력할 경우 설정된 WORKDIR에 복사한다
예) COPY build/libs/app.jar app.jar
→ 호스트 시스템 내 build/libs/app.jar 파일을 WORKDIR 위치에 app.jar라는 이름으로 복사한다
- 호스트 시스템의 파일/디렉토리를 이미지에 복사한다.
ADD
ADD source(로컬 파일) dest(이미지 내 위치)
- 호스트 시스템의 파일/디렉토리를 이미지에 복사한다는 점에선 동일하다. 하지만 ADD는 그 외 두 가지 기능을 더 제공한다.
- 자동 압축해제
복사 대상 파일이 압축 파일(tar, tar.gz)일 경우 압축을 해제하여 복사한다 - Remote file URL
호스트 시스템의 파일/디렉토리가 아닌 URL을 사용해 복사할 수 있다
- 자동 압축해제
ENTRYPOINT
1) ENTRYPOINT <전체 명령문>
2) ENTRYPOINT ["<명령문>", "<파라미터1>", "<파라미터2>"]
*일반적으로 2번을 사용한다
예1) ENTRYPOINT ["java", "-jar", "/app.jar"]예) ENTRYPOINT ["npm", "start"]
예2) ENTRYPOINT ["python", "app.py", "param1"]
- 이미지를 컨테이너로 실행시킬 때 항상 실행되는 명령어를 지정한다.
- 생략할 수 있으며, 생략될 경우 커맨드에 지정된 명령어로 수행
CMD
1) CMD ["<명령문>","<파라미터1>","<파라미터2>"] : exec form
2) CMD ["<파라미터1>","<파라미터2>"] : ENTRYPOINT의 parameter로 사용
3) CMD <전체 커맨드> : shell form
예1) CMD에 실행 명령문 입력
[Dockerfile]
CMD echo "echo from CMD" // 실행 명령문
[docker run 실행 시 실행 명령문 지정 X]
$ docker run -it <image-name>
결과) echo from CMD
[docker run 실행 시 실행 명령문 지정 O]
$ docker run -it <image-name> echo "echo from docker run"
결과) echo from docker run
예2) CMD에 ENTRYPOINT 인수로 사용
[Dockerfile]
ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]
[docker run 실행 시 실행 명령문 지정 X]
$ docker run -it <image-name>
결과) app.jar 실행
[docker run 실행 시 실행 명령문 지정 O]
$ docker run -it <image-name> run.jar
결과) run.jar 실행
- 도커 컨테이너가 실행될 때 수행할 명령어(예1) 또는 ENTRYPOINT의 인수(arguments)가 될 수 있는데(예2), 일반적으로 ENTRYPOINT의 인수로 사용된다.
- CMD와 ENTRYPOINT는 기본적으로 같은 동작을 한다. 차이점은 ENTRYPOINT는 명시된 내용을 바꿀 수 없지만 CMD의 경우 docker run 실행시 커맨드를 입력해 CMD에 명시된 내용을 바꿔 실행시킬 수 있다.
- CMD는 도커 파일 내 한 번만 적용된다. 만약 여러 개의 CMD가 작성되었을 경우 마지막 CMD만 적용된다.
- docker run 실행시 커맨드를 입력하지 않으면 CMD에서 설정한 값이 실행된다. (예1의 실행 명령문 지정 X 참고)
- 컨테이너에 적용된 엔트리포인트와 커맨드는 docker inspect 명령어 입력 후 "Config"에서 "Cmd", "Entrypoint" 항목에서 확인할 수 있다.
EXPOSE
EXPOSE <port> [<port>/<protocol>...]
예)
[Dockerfile]
EXPOSE 80
[docker run 실행 시 -p로 매핑]
docker run -it <image-name> -p 80:80
결과) 80->80/tcp
[docker run 실행 시 -P로 매핑]
docker run -it <image-name> -P
결과) 15548->80/tcp
- 컨테이너가 EXPOSE에서 지정한 포트를 수신(listen)하도록 명시한다. 즉, "이 컨테이너는 <port>를 외부에 공개한다" 라고 설정하는 것과 같다.
- <protocol>로 TCP 또는 UDP를 지정할 수 있으며 지정하지 않을 경우 TCP가 디폴트다.
- 주의할 점은 EXPOSE로 포트를 지정했다고 해서 해당 포트가 호스트 시스템에 공개(publish)된건 아니라는 것이다. 실제 호스트 시스템에 연결되기 위해선 docker run 명령어에서 -p 옵션으로 포트를 매핑하거나 또는 -P 옵션을 사용해야 한다.
- [참고]
포트 매핑 결과는 'docker ps' 명령어 입력 후 PORTS 항목에서 확인할 수 있다
ENV
ENV <key>=<value>
예1) ENV MY_NAME="John Doe"
→ "는 제거됨
예2) ENV MY_DOG=Rex\ The\ Dog
→ white space를 넣고 싶을땐 \(back slash)를 사용
예3) ENV MY_CAT=fluffy
- 환경변수 설정을 하는데 사용한다. 환경변수는 이미지를 빌드할 때 사용되며, 이미지로 실행된 컨테이너에서도 접근할 수 있다.
- docker inspect 명령어를 통해 "Config" > "Env" 항목을 통해 정의된 환경변수를 확인할 수 있고, 'docker run --env ='를 통해 수정할 수 있다.
- value에 "를 사용할 때 escape가 아닐 경우 제거된다.
- [참고] docker 명령어의 -e 옵션을 통한 환경변수 설정
-e 옵션을 통해 환경변수 설정을 할 수 있다. 예) docker run -it -e MY_HOST=fastcampus.com ubuntu bash - [참고] 환경변수 설정시 컨테이너에서의 영향을 고려해야 한다
컨테이너에서도 환경변수가 남기 때문에 다른 프로그램에서 사용하는 용어를 잘못 설정할 경우 예상치 못한 side effect가 발생할 수 있다. 예컨대, ENV DEBIAN_FRONTEND=noninteractive 로 지정할 경우, apt-get 명령어가 비정상 동작할 수 있다. 이런 문제는 ARG 명령어를 사용하면 해결할 수 있다. ARG 명령어를 통해 정의된 변수는 최종 이미지에서 제거되기 때문이다.
ARG
1) ARG <name> : docker build 명령어에서 value 지정
2) ARG <name>=<default value> : docker build 명령어에서 지정하지 않을 때 사용할 기본값 지정
예1) ARG 사용법
[Dockerfile]
ARG user1
ARG user2=banana # user2의 기본값을 banana로 설정
[docker 명령어]
$ docker build --build-arg user1=citron
결과) 이미지 빌드시 user1은 citron, user2는 banana가 사용됨
예2) multiple build stage에서 동일 ARG 변수 사용
[Dockerfile]
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
→ RUN 실행했으므로 ARG SETTINGS는 제거됨
FROM busybox
ARG SETTINGS
RUN ./run/other $SETTINGS
- docker build 명령어 사용시 --build-arg <varname>=<value> 옵션을 통해 넘기고 싶은 인자(argument)를 정의한다.
- 도커파일 내 ARG 명령어를 정의하기 전의 line에서 변수를 사용하면 빈 문자열이 생성된다.
- ARG 명령어로 생성된 변수는 각 빌드 단계(build stage)가 끝나면 제거된다. 따라서 여러 빌드 단계(multiple stages)에서 사용하고 싶다면 각 빌드 단계에 ARG 명령어로 변수를 지정해줘야 한다.
*build stage는 하나의 RUN 명령어 실행을 말하는 듯. 즉, RUN 명령어를 실행후에는 이전에 정의한 ARG 변수를 다시 정의해줘야한다. → 예2 참고 - 도커파일에서 정의하지 않은 인자를 docker build 명령어에서 사용할 경우 해당 인자가 사용되지 않는다는 warning 메시지를 띄운다
- ARG 명령어로 보안상 노출되면 안되는 값은 사용하지 않을 것을 경고하고 있다. ARG 명령어와 같은 Build-time 변수는 docker history 커맨드를 통해 노출되기 때문이다.
LABEL
LABEL <key>:<value>
예)
[Dockerfile]
LABEL author="citronbanana"
LABEL version="1.0"
[docker 명령어]
docker image inspect --format='' <image-name>
- 이미지에 대한 metadata(이미지의 버전 정보, 작성자, 코멘드 등)를 작성하는데 사용된다
- docker image inspect --format='' <image-name>으로 확인할 수 있다
기타
# : 주석
❑ REFERENCE
Dockerfile Official Reference | https://docs.docker.com/engine/reference/builder/
https://www.daleseo.com/dockerfile/
https://jfrog.com/knowledge-base/a-beginners-guide-to-understanding-and-building-docker-images/
'DevOps > Docker' 카테고리의 다른 글
[Docker] 기초 시리즈 (5) 도커 이미지 다루기 - Docker Hub(Registry) (0) | 2022.06.07 |
---|---|
[Docker] 기초 시리즈 (8) 자주 사용하는 도커 명령어 모음 (0) | 2022.05.14 |
[Docker] 기초 시리즈 (6) 도커 이미지 다루기 - 이미지 직접 생성 (0) | 2022.04.30 |
[Docker] 기초 시리즈 (2) Ubuntu에 도커 엔진 설치 (0) | 2022.04.30 |
[Docker] 기초 시리즈 (4) 도커 이미지의 구조 (0) | 2022.04.29 |