이제 도커 이미지를 Dockerfile
을 이용해 만들어보겠습니다.
이전에 도커 이미지 게시글에서 잠깐 다뤘던 그림을 가져오겠습니다.
도커파일의 특징
도커 파일의 문법
첫번째 줄은 이 이미지의 기반 이미지가 무엇인지에 대해서 적어주는 것 입니다.
예를 들어 백엔드가 없는 자바스크립트 어플을 만드는 상황을 가정해보겠습니다.
이미지의 nodejs
가 Base이미지
인 이미지의 구조는 다음과 같습니다.
우리는 Linux Alpine
또는 다른 lower level
이미지가 필요합니다. 이후 우리는 node를 설치해야만 합니다. app의 기반이미지는 nodejs엔진입니다. 노드엔진의 기반 운영체제도 있습니다.
실제로 우리의 이미지가 NODE 이미지
에 기반으로 한다면, 우리의 이미지 안에 노드를 설치해야한다는 것을 의미합니다. 따라서 우리가 컨테이너 쉘을 열면 node
명령이 사용가능한 것을 볼 수가 있습니다.
도커파일 예시 문법
예시를 들어보겠습니다.
기본적으로 도커파일은 쉘에서 실행할 수 있는 명령을 전부 실행할 수 있다고 했습니다.
따라서 쉘명령을 도커파일로 변경한 모습을 보도록 하겠습니다.
쉘 명령
install node
set MONGO_DB_USERNAME=addmin
set MONGO_DB_PWD=password
create /home/app folder
copy current foler file to /home/app
start the app with: "node server.js"
도커 파일
FROM node
ENV MONGO_DB_USERNAME=admin \
MONGO_DB_PWD=password
RUN mkdir -p /home/app
COPY . /home/app
CMD ["node", "server.js"]
간단하게 노드를 기반으로 하는 웹서버를 실행하는 상황을 도커파일로 만들었습니다.
위 내용을 기반으로 도커파일의 문법에 대해서 설명하도록 해보겠습니다.
도커파일 문법
FROM
FROM node
: 노드 이미지를 기반으로 합니다.
위에서 이야기 했듯 모든 도커파일은 FROM
으로 시작합니다.
FROM
명령문은 기본적으로 사용할 Base 이미지
를 지정합니다.
Docker 이미지는 여러 계층으로 구성되며, FROM
명령문은 이러한 계층 중 가장 첫 번째 계층을 정의합니다.
RUN
run mkdir -p /home/app
: 이 부분은 /home/app
이라는 폴더가 컨테이너 내부에 생성되게 된다는 것을 의미하게 됩니다. (로컬에 폴더가 생기는 것이 아닙니다.)
이 폴더 내부에 이미지나 도커파일 등 설정파일과 다양한 것들이 들어가게 됩니다.
RUN 명령
을 사용하면 기본적으로 모든 종류의 Linux 명령을 실행할 수 있습니다.
COPY
COPY 호스트_파일경로 , 도커컨테이너_내부경로
만약 COPY
를 가장 마지막에 두는 경우 도커 컨테이너 내부에 있는 파일을 복사 할 수가 있습니다.
COPY . /home/app
: 첫번째 매개변수는 source(.)
이고 두번째 매개변수는 target(/home/app)
입니다. 도커파일이 있는 위치에서, 있는 모든 파일을 컨테이너 위에 /home/app
으로 복사가 됩니다!!
CMD
CMD
명령의 3가지 양식
1. CMD ["executable","param1","param2"]
(실행 양식, 이 양식이 기본 양식입니다.)
2. CMD ["param1","param2"]
(ENTRYPOINT
의 기본 파라미터로 사용)
3. CMD command param1 param2
(쉘 형태)
cmd ["node", "server.js"]
우리가 노드로 서버를 시작하는 명령을 실행하는 예시입니다.
실제로 우리가 커맨드라인에서 서버를 실행할 때 node server.js
라고 입력합니다.
즉 node server.js
를 컨테이너 내부에서 실행하도록 하는 의미입니다.
CMD
의 기본 목적은 실행중인 컨테이너에 기본값을 제공하는 것 입니다.
환경변수 대체
CMD [ "echo", "$HOME" ]
형식은 환경변수 대체를 해주지 않습니다. 왜냐하면 양식 1,2번 같은 경우 기본적으로 쉘 위에서 실행되는게 아니기 때문에 그렇습니다.
만약 환경변수를 대체하고 싶다면, CMD [ "sh", "-c", "echo $HOME" ]
로 쉘을 이용해 환경변수 대체를 해줄 수 있습니다.
RUN
과 CMD
차이점.
RUN
과 CMD
는 비슷해 보이지만, 큰 차이가 있는데, CMD
는 entrypoint command
를 의미합니다.
즉, RUN
명령은 여러 번 실행할 수 있지만 CMD
명령은 오직 한번만 파일에 있을 수 있습니다.
CMD
명령은 오직 도커파일에서 한번만 쓰는게 원칙이지만 만약 여러개가 들어갔다면 마지막 CMD
를 사용합니다.
그리고 CMD
는 ENTRYPOINT
와 결합해서 진입점을 정합니다.
ENTRYPOINT
엔트리 포인트는 2개의 형식이 있습니다.
ENTRYPOINT ["executable", "param1", "param2"]
: 기본 형식
ENTRYPOINT command param1 param2
: 셸 형식
ENTRYPOINT
를 통해 실행 파일로 실행할 컨테이너를 구성할 수 있습니다.
기본형식
다만 ENTRYPOINT
를 잠깐 바꾸고 싶다면 docker run --entrypoint
flag
를 사용하면 그 RUN
명령에서는 overriding
됩니다.
예시
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
다음과 같은 실행결과가 나옵니다.
즉, 이걸 보면, PID 1
번으로 실행하는 프로그램이 ENTRYPOINT
로 지정해준 프로그램임을 볼 수 있습니다.
아파치의 엔트리 포인트 예시
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
ENTRYPOINT
를 지정해줌으로써, 그 컨테이너에서 실행할 때 그곳으로 들어가서 실행을 합니다.
즉 컨테이너에서 첫번째로 실행하는 프로세스를 지정할 때 유용하게 사용할 수도 있습니다.
쉘형식
쉘 형식 같은 경우에는 ENTRYPOINT
가 /bin/sh -c
로 실행이 됩니다.
따라서, 첫번째 PID1
이 쉘이 되고 그 다음으로 실행하는 명령으로 될 것이기 때문에 컨테이너가 유닉스 시그널을 받지 않습니다.
그래서 시그널을 받아도 실행한 것이 stop
하지 않고 쉘이 중단
한다는 특징이 있습니다.
저희 과제에서는 금지된 방법이라고 생각하셔도 좋습니다.
CMD와 ENTRYPOINT의상호 작용 방식 이해
CMD
와 ENTRYPOINT
규칙
ENTRYPOINT
와 CMD
사용 조합표
다음 표는 ENTRYPOINT
와 CMD
사이의 조합을 보여주는 표입니다.
각각 ENTRYPOINT
와 CMD
모두 쉘 버전으로 실행하면 ([] 대괄호가 없는 버전
) 전부 /bin/sh(본쉘)
를 이용해서 실행하는 모습을 볼 수가 있습니다.
그 외 특징은 언제나 ENTRYPOINT
가 먼저 실행된다는 점과, 엔트리포인트가 쉘 형식이면 CMD
가 무시된다는 특징을 볼 수 있습니다.
만약 CMD와 ENTRYPOINT 설명이 이해가 안가면 나중에 실습하다 궁금증이 생길 때
여기서 CMD
와 ENTRYPOINT
에 대해서 더 이해를 하고 넘어가기를 바랍니다.
EXPOSE
컨테이너에게 반드시 Expose
해야만 하는 포트번호를 적어줍니다.(컨테이너 내부 포트를 의미합니다.)
expose:
- "3000"
- "8000"
컨테이너 내부의 포트번호만을 지정해줄 수 있습니다.
즉 컨테이너 내부에서 통신할 포트 번호를 적어준다라고 생각해주시면 좋을 것 같습니다.
publish
하려면 -p
플래그를 Docker run
할 때 줘야만 합니다.
ARG
FROM
은 ARG
앞에 올수 있는 유일한 지침입니다.
또한 FROM
같은 경우 as name
으로 기반 이미지의 이름을 적을 수 있습니다.
ARG <이름>
ARG <이름>=<기본값>
다음과 같은 방법으로 도커파일
로 컨테이너에게 환경변수를 만들어 전달 할 수 있습니다.
ARG
명령문은 docker build
커맨드로 이미지를 빌드 시, --build-arg
옵션을 통해 넘길 수 있는 인자를 정의하기 위해 사용합니다.
$ docker build --build-arg port=8080 .
: 예를 들어, Dockerfile
에 다음과 같이 ARG
명령문으로 port
를 인자로 선언해주면, docker build
커맨드에 --build-arg
옵션에 port
값을 넘길 수가 있습니다.
ARG port=8080
처럼, 인자의 디폴트값을 지정해주면, --build-arg
옵션으로 해당 인자가 넘어오지 않았을 때 사용됩니다.
CMD start.sh -h 127.0.0.1 -p ${port}
: 설정된 인자 값은 다음과 같이 ${인자명}
형태로 읽어서 사용할 수 있습니다.
도커파일의 문제 및 환경변수 설정
도커파일은 도커파일이 수정될 때마다 수정된 부분만 바꾸는게 아니라 이미지를 다시 빌드해야만 합니다.
환경변수 설정은 도커 컴포즈에서도 할 수 있습니다. 사실 이것은 둘 중 어디서 설정해주던 다 설정이 가능합니다. 이는 선택에 따라 달라집니다.
도커파일 빌드해보기 docker build
docker build [OPTIONS] PATH | URL | -
docker build -t my-app:1.0 .
첫번째 인자는 이미지에 이름을 지정하도록 이미지 이름을 인자로 사용합니다.
두번째 인자는 도커파일의 위치입니다.
위의 명령의 의미는 이미지의 이름을 my-app
으로 하고 버전을 1.0으로 합니다. 또, 도커파일의 위치는 현재 폴더와 같은 위치에 있다는 의미입니다.
다음과 같은 명령으로 도커이미지를 지울 수 있습니다.
docker stop
docker rm
docker rmi
이전 게시물에서 다뤘기 때문에 이미지로 대체합니다.
Uploaded by N2T
'42Seoul > Inception' 카테고리의 다른 글
컨테이너 빌드에 대한 권장사항 [PID 1] [42 inception 과제 개념11] (0) | 2023.06.24 |
---|---|
Docker Volume이란? [42 inception 과제 개념 10] (0) | 2023.06.24 |
docker compose를 사용한 네트워크 [42 inception 과제 개념 8] (0) | 2023.06.24 |
docker compose 명령어 [42 inception 과제 개념 7] (0) | 2023.06.24 |
docker-compose 란 무엇인가? [42 inception 과제 개념 6] (0) | 2023.06.24 |