bxm's IT Story
Docker (#7. 기타 도커 명령어, Dockerfile로 빌드 할 때 주의할 점, 도커 데몬) 본문
## 기타 Dockerfile 명령어 ##
// 미리 말하는데 ENV는 환경변수라서 대상에 빠르게 접근이 가능하고,
VOLUME은 호스트의 볼륨과 서로 공유를 하기에 편하고,
USER는 아무나 root 계정에 접근하면 안되므로, 딱 정해주는 것임!! 그래서 su 를 쳐도 류트계정으로 못들어옴 ㅎㅎ
chmod로 권한 주면 되지 않느냐!! 할 수 있는데 그걸로 root 계정 접근을 막을 수는 없다!! ㅎㅎㅎㅎ
T 피셜, 클라우드 중급 이상으로 다루는 엔지니어가 되면 훨씬 더 편할텐데 아직은 공감이 안될 거라고 하심.
1) ENV, VOLUME, ARG, USER
- ENV (Environment; 뒤의 ARG와 비슷하다!)
: Dockerfile에서 사용될 환경변수를 지정한다. 설정한 환경변수는 ${ENV_NAME} 또는 $ENV_NAME 의 형태로
사용할 수 있다. 이 환경변수는 Dockerfile 뿐만 아니라 이미지에도 저장되므로 빌드된 이미지로 컨테이너를
생성하면 이 환경변수를 사용할 수 있다.
vi Dockerfile
FROM ubuntu:14.04 ENV test /home WORKDIR $test RUN touch $test/mytouchfile ![]() |
// 이미지 빌드하기
docker build -t myenv:0.0 ./
// 컨테이너 생성
docker run -it --name myenv myenv:0.0
// 여기서 echo $test 하면 어떤 일이 발생할까?
Docker1 - myenv]
echo $test
// 한번 환경변수를 통해서 이동해보자!! 되는지 확인!!
cd /
cd $test
- 'VOLUME' 을 활용한 Dockerfile
Docker1]
vi Dockerfile
FROM ubuntu:14.04 RUN mkdir /home/volume RUN echo test >> /home/volume/testfile VOLUME /home/volume ![]() |
// 이미지를 빌드한 뒤에 컨테이너를 생성하고, 볼륨의 목록을 확인해보면 컨테이너 내부의 /home/volume 디렉토리를
호스트와 공유하고 있다.
docker build -t myvolume:0.0 ./
// 컨테이너 생성
docker run -itd --name volume_test myvolume:0.0 ./
// 호스트와 볼륨을 공유하는 것을 확인
docker volume ls
cd /var/lib/docker/volumes/7ac6eca6ec8fe49a9adb51983605831242f4223570ec849733aeb9a0103a6af3
cd /var/lib/docker/volumes/
find ./ -name testfile
- ARG (실제로 그렇게 많이 쓰이진 않는다.)
: build 명령어를 실행할 때 추가로 입력을 받아 Dockerfile 내에서 값을 설정한다.
다음 Dockerfile은 build 명령어에서 my_arg와 my_arg_2라는 이름의 변수를 추가로 입력받을 것이라고 ARG를
통해 명시하고 있다. ARG의 값은 기본적으로 build 명령어에서 입력받아야 하지만, 다음의 my_arg_2와 같이
기본값을 지정할 수도 있다.
cd /temp
vi Dockerfile
FROM ubuntu:14.04 MAINTAINER baaaam ARG my_arg ARG my_arg_2=value2 RUN touch ${my_arg}/mytouch ![]() |
build 명령어를 실행할 때 [--build-arg] 옵션을 사용해 Dockerfile의 ARG에 값을 입력할 수 있다.
형식은 '<키>=<값>' 과 같이 쌍을 이뤄야 한다.
docker build --build-arg my_arg=/home -t myarg:0.0 ./
ARG와 ENV 의 값을 사용하는 방법은 ${}로 같으므로 Dockerfile에서 ARG로 설정한 변수를 ENV에서 같은 이름으로 다시 정의하면 --build-arg 옵션에서 설정하는 값은 ENV에 의해 덮어쓰여진다.
위의 Dockerfile 예제에서는 $(my_arg)의 디렉토리에 mytouch 라는 파일을 생성했기 때문에 빌드된 이미지로
컨테이너를 생성해 확인하면 mytouch라는 이름의 파일을 확인할 수 있다.
docker run -it --name arg_test myarg:0.0
Docker1 - arg_test]
ls /home/mytouch
- USER
: USER로 컨테이너 내에서 사용될 사용자 계정의 이름이나 UID를 설정하면, 그 아래의 명령어는 해당 사용자
권한으로 실행된다. 일반적으로 RUN 으로 사용자의 그룹과 계정을 생성한 뒤 사용한다.
루트 권한이 필요하지 않다면 USER를 사용하는 것을 권장한다.
vi Dockerfile
FROM ubuntu:14.04 MAINTAINER baaam93 RUN groupadd -r author && useradd -r -g author baaam93 USER baaam93 ![]() |
docker build -t myuser:0.0 ./
// 컨테이너 생성
docker run -it --name myuser myuser:0.0
Docker1 - myuser]
whoami


2) Stopsignal, Healthcheck
- STOPSIGNAL
: 컨테이너가 정지될 때 사용될 시스템 콜의 종류를 지정한다. 아무것도 설정하지 않으면 기본적으로 'SIGTERM' 으로
설정되지만, Dockerfile에 STOPSIGNAL을 정의하여 컨테이너가 종료되는데 사용될 신호를 선택할 수 있다.
다음은 Dockerfile에서 STOPSIGNAL을 SIGTERM이 아닌 'SIGKILL'로 지정한 예이다.
Docker1]
vi Dockerfile
FROM ubuntu:14.04 STOPSIGNAL SIGKILL ![]() |
docker build ./ -t stopsignal:0.0
docker run -itd --name stopsignal_container stopsignal:0.0
docker inspect stopsignal_container | grep Stop
// 시그널(Signal)은 프로세스 또는 시스템에게 이벤트 발생을 전달하는 신호이다.
SIGKILL | KILL, 실행 중인 프로세스를 강제 종료할 때 사용한다. // 컨테이너가 실행될 때 아파치도 같이 실행되고 있다...! 그러면 아파치도 강제로 종료하겠다! 라는 뜻! // 이 신호를 안주면 불시에 종료되어버리는 것이다. |
SIGTERM | Terminate, 정상적인 종료 방법이다. |
SIGSCONT | 중지된 프로세스를 실행할 때 사용한다. |
SIGSTOP | SIGCONT 시그널을 받을 때 사용한다. |
SIGTSTP | 프로세스 대기로 전환할 때 사용한다. |
kill -l
- HEALTHCHECK (중요한 개념이 아니므로 실습 X)
: 이미지로부터 생성된 컨테이너에서 동작하는 어플리케이션의 상태를 체크하도록 설정한다.
3) ADD, COPY
- ADD
: COPY는 로컬 디렉토리에서 읽어 들인 컨텍스트로부터 이미지에 파일을 복사하는 역할을 한다. COPY를 사용하는
형식은 ADD와 같다.
COPY test.html /home
COPY ["test.html", "/home/"]
COPY는 로컬파일만 이미지에 추가할 수 있지만, ADD는 외부 URL 및 tar 파일에서도 파일을 추가할 수 있다는 점이
다르다. COPY의 기능이 ADD에 포함되는 셈이다.
ADD https://raw.githubusercontent.com/alicek106/mydockerrepo/master/test.html /home
다음과 같이 tar 파일을 추가할 수도 있다.
ADD test.tar /home
그러나 ADD를 사용하는 것은 그다지 권장하지 않는다. 그 이유는 ADD로 URL이나 tar 파일을 추가할 경우
이미지에 정확히 어떤 파일이 추가될지 알 수 없기 때문이다.
vi Dockerfile
FROM ubuntu:14.04 MAINTAINER baaam93 // 저작자가 누군지 보여주는 것이므로 안써도 그만이다 ㅎㅎ COPY test.html /home ADD https://www.google.com/url?sa=i&url=http%3A%2F%2Fwww.nongupin.co.kr%2Fnews%2FarticleView.html%3Fidxno%3D63937&psig=AOvVaw0FT3qQq6CeNhlm3XTop1_J&ust=1632978449854000&source=images&cd=vfe&ved=0CAgQjRxqFwoTCIiSw_W0o_MCFQAAAAAdAAAAABAD /home ![]() |
// 빌드를 해보자
docker build . -t COPY_ADD_TEST:0.0 ==> 대문자로 하면 안된다고 뜬다.
docker build . -t copy_add_test:0.0
docker run -it --name add_copy_test copy_add_test:0.0
Docker1 - add_copy_test]
cd home
ls -l


## Dockerfile로 빌드할 때 주의할 점 ##
.dockerignore 파일을 작성해 불필요한 파일을 빌드 컨텍스트에 포함하지 않는 것은 좋은 습관이라 하겠다.
1) 잘못된 Dockerfile 사용법
vi Dockerfile
FROM ubuntu:14.04 RUN mkdir /test RUN rm /test/dummy |
2) 바람직한 Dockerfile 사용법
vi Dockerfile
FROM ubuntu:14.04 RUN mkdir /test && mkdir /test2 ==> 이렇게 RUN 명령어를 하나로 묶으면 이미지 레이어의 개수 또한 하나로 줄어든다!!!!! ![]() |
// 다른 사람이 빌드한 이미지에 불필요한 이미지 레이어가 들어있다면 해당 이미지로 컨테이너를 생성하고
docker export, import 명령어를 사용해 컨테이너를 이미지로 만듦으로써 이미지의 크기를 줄일 수 있다.
익스포트(export)된 파일을 임포트해서 다시 도커에 저장하면 레이어가 한개로 줄어든다. 그러나 이전 이미지에
저장되어 있던 각종 이미지 설정은 잃어버리게 되므로 주의해야 한다.
docker build . -t falloc_100mb:0.0
docker build . -t falloc_100mb:0.0
docker run -it --name temp falloc_100mb:0.0
docker export temp | docker import - falloc_100mb:0.1
docker run -itd --name temp2 falloc_100mb:0.1
// 위 예에서는 베이스 이미지인 ubuntu:14.04 이미지의 커맨드 명령어가 손실되어 설정되지 않았고,
entryport 또한 설정되지 않아 에러를 출력하며 컨테이너가 생성되지 않는다.
## 도커 데몬 ##
1) 도커의 구조
which docker
ps aux | grep docker
컨테이너나 이미지를 다루는 명령어는 /usr/bin/docker에서 실행되지만, 도커 엔진의 프로세스는 /usr/bin/dockerd
파일로 실행되고 있다. 이는 docker 명령어가 실제 도커 엔진이 아닌 클라이언트로써의 도커이기 때문이다.
실제로 컨테이너를 생성하고 실행하며 이미지를 관리하는 주체는 도커 서버이고, 이는 dockerd 프로세스로서
동작한다. 도커 엔진은 외부에서 API 입력받아 도커 엔진의 기능을 수행하는데, 도커 프로세스가 실행되어 서버로서
입력을 받을 준비가 된 상태를 도커 데몬이라고 한다.
도커 데몬은 API 입력을 받아 도커 엔진의 기능을 수행하는데, 이 API를 사용할 수 있도록 CLI 를 제공하는 것이 도커
클라이언트이다. 사용자가 docker로 시작하는 명령어를 입력하면. 도커 클라이언트를 사용하는 것이며, 도커
클라이언트는 입력된 명령어를 로컬에 존재하는 도커 데몬에게 API로서 전달한다.
이때 도커 클라이언트는 /var/run/docker.sock에 위치한 유닉스 소켓을 통해 도커 데몬의 API를 호출한다. 도커
클라이언트가 사용하는 유니스 소켓은 같은 호스트 내에 있는 도커 데몬에게 명령을 전달할 때 사용된다. 즉 터미널이나 PuTTY등으로 도커가 설치된 호스트에 접속해 docker 명령어를 입력하면 아래와 같은 과정으로 도커가 제어된다.
1. 사용자가 docker ps 같은 도커 명령어를 입력한다. |
2. /usr/bin/docker는 /var/run/docker.sock 유닉스 소켓을 사용해 도커 데몬에게 명령어를 전달한다. |
3. 도커 데몬은 이 명령어를 해석하고 명령어에 해당하는 작업을 수행한다. |
4. 수행 결과를 도커 클라이언트에게 반환하고 사용자에게 결과를 출력한다. |
## 도커 데몬 실행 ##
도커 데몬 실행 | service docker start |
도커 데몬 정지 | service docker stop |
// 레트헷 계열의 운영체제는 도커를 설치해도 자동으로 실행되지 않으므로 다음과 같이 한다.
systemctl enable docker
// 앞서 설명했듯이 도커 서비스는 dockerd로 도커 데몬을 실행한다. 그러나 서비스를 실행하지 않고 직접 도커 데몬을 실행할 수도 있다.
service docker stop
dockerd
dockerd를 입력하면 도커 데몬이 실행된다. 이러면 입력을 받을 수 있는 상태가 되는데 터미널을 하나 더 연 다음 도커 명령어를 입력하면 이전처럼 도커를 사용할 수 있다. 터미널에 실행된 도커 데몬을 종료하려면 Ctrl+C를 입력하면 된다.
1) 도커 데몬 제어 : -H
-H 옵션은 도커 데몬의 API를 사용할 수 있는 방법을 추가한다. 아무런 옵션을 설정하지 않고 도커 데몬을 실행하면
도커 클라이언트인 /usr/bin/docker/를 위한 유닉스 소켓인 /var/run/docker.sock 을 사용한다. 그러므로 단순히 dockerd를 입력해도 도커 큵라이언트의 CLI를 사용할 수 있다. 즉, 다음 두 명령어의 차이는 없다.
dockerd // dockerd 명령어를 치면, 해당 터미널에서는 입출력이 없는게 당연하다고 한다!!
멈춘게 당연하고 여기서 다시 docker server를 사용하려면, [Cntl+C]로 중지한 뒤에
'service docker start' 명령어를 수행하면 된다.
docker -H unix///var/run/docker.sock
## 도커 데몬 모니터링 ##
1. 디버그 모드
: 디버그 모드는 도커 데몬을 실행할 때 -D 옵션을 추가해서 사용한다.
docker -D
이것을 GUI 로 방식으로 보려면 CAdvisor 와 같은 모니터링 도구를 사용한다.
docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:ro --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor:latest
Host PC]
http://10.10.32.81:8080
CAdvisor의 대시보드는 60초간의 모니터링 정보만 보여주지만 InfluxDB나 Prometheus 등과 같이 사용하면 장기간의
모니터링 정보를 수집하고 분석 할 수 있다.
여기서 옵션으로 설정한 호스트 볼륨 공유(-volume~) 부분에 주목할 필요가 있다. 이 옵션으로 인해 수 많은 정보를
보여 줄 수 있는데 그 이유는 호스트의 모든 디렉토리를 CAdvisor 컨테이너에 볼륨으로 마운트했기 때문이다.
/var/run에는 도커를 로컬에서 제어하기 위한 유닉스 소켓이 있고, /sys 에는 도커 컨테이너를 위한 cgroup 접보가 저장되어 있으며 /var/lib/docker에는 도커의 컨테이너, 이미지 등이 파일로 존재한다.
CAdvisor은 단일 도커 호스크만을 모니터링할 수 잇다는 한계가 있다. 여러 개의 호스트로 도커를 사용하고 있다면
쿠버네티스나 스웜 등을 서치한 뒤에 프로메데우스(Prometheus), InfluxDB 등을 이용하는 것이 일반적이다.






'가상화 > Docker' 카테고리의 다른 글
Docker (#9. 스웜 서비스 장애 복구, 서비스 롤링 업데이트, 스웜 동작 원리) (0) | 2021.09.30 |
---|---|
Docker (#8. 도커 스웜[기본 세팅, 스웜 구축, 스웜 모드 서비스]) (0) | 2021.09.29 |
Docker (#6. 도커 사설 레지스트리, 도커 파일) (0) | 2021.09.28 |
Docker (#5. 도커 이미지, 도커 허브, 도커 파일) (0) | 2021.09.28 |
Docker (#4. 컨테이너 로깅, 컨테이너 자원 할당) (0) | 2021.09.27 |