Katacoda를 이용한 Docker 공부 4일차 정리

이 포스트는 Korea Azure User Group에서 진행하는 Docker/Container 스터디 그룹에 참여하며 작성했습니다.

스터디를 진행한 Katacoda 강좌: Docker & Containers(https://katacoda.com/courses/docker)

진행한 강의 목록

  • Ensuring Container Uptime With Restart Policies
  • Adding Docker Metadata & Labels
  • Load Balancing Containers
  • Orchestration using Docker Compose

스터디는 Katacoda의 화면을 참조하되, 실습은 제 개인 PC에서 VM을 구성해서 진행했습니다. 따라해볼 수 있는 것만 별도로 정리했습니다.

구성환경

  • Windows 10 Pro 1809
  • Hyper-V
  • CentOS 7.6.1810 (Kernel 4.20.2-1.el7)

내용 정리

# 컨테이너에 오류 발생시 일시정지 상태로 되기 때문에, 재시작 옵션 등을 통하여 정상 실행을 기대할 수 있다.
[root@docker-master ~]# docker run -d --name res-default scrapbook/docker-restart-example # 테스트용 컨테이너 생성
Unable to find image 'scrapbook/docker-restart-example:latest' locally
latest: Pulling from scrapbook/docker-restart-example
e190868d63f8: Pull complete 
909cd34c6fd7: Pull complete 
0b9bfabab7c1: Pull complete 
a3ed95caeb02: Pull complete 
89132a5c7e46: Pull complete 
Digest: sha256:426b72cb24b716bb4b018cb4ea87b9d65df89d5320ec50bf9ccc3c2c6f99b5ca
Status: Downloaded newer image for scrapbook/docker-restart-example:latest
22f941498999efc0dce5d49a0f00539e0fe4750adade2f8de6f875e1a2853085
[root@docker-master ~]# docker ps -a # 컨테이너 확인
CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS                          PORTS                         NAMES
22f941498999        scrapbook/docker-restart-example     "/bin/sh -c ./launch…"   36 seconds ago      Exited (1) 35 seconds ago                                     res-default
[root@docker-master ~]# docker logs res-default # 로그확인시 컨테이너 실행 확인, 일시 중지도 확인
Thu Mar 21 05:00:38 UTC 2019 Booting up...
[root@docker-master ~]# docker run -d --name res-3 --restart=on-failure:3 scrapbook/docker-restart-example # 실패시 최대 3회까지 재시작
f4431c7908c9d349d64934b11b206e46ea172fb865d02e1054a242bb4ea32b34
[root@docker-master ~]# docker logs res-3 # 로그가 총 4회(시작 1회, 재시작 3회)
Thu Mar 21 05:02:35 UTC 2019 Booting up...
Thu Mar 21 05:02:36 UTC 2019 Booting up...
Thu Mar 21 05:02:38 UTC 2019 Booting up...
Thu Mar 21 05:02:39 UTC 2019 Booting up...
[root@docker-master ~]# docker run -d --name res-alw --restart=always scrapbook/docker-restart-example # 충돌시 무조건 재시작 설정
f9c274e46ec7ae4c6ea8e7b9b3edbad64b4ca457b0c03aa58801cd9120a35d27
[root@docker-master ~]# docker logs res-alw # 로그 확인시 부팅 1회, 나머지 재시작 확인
Thu Mar 21 05:03:21 UTC 2019 Booting up...
Thu Mar 21 05:03:22 UTC 2019 Booting up...
Thu Mar 21 05:03:24 UTC 2019 Booting up...
Thu Mar 21 05:03:26 UTC 2019 Booting up...
Thu Mar 21 05:03:28 UTC 2019 Booting up...
[root@docker-master ~]# docker logs res-alw # 지속적인 부팅 시도 증가
Thu Mar 21 05:03:21 UTC 2019 Booting up...
Thu Mar 21 05:03:22 UTC 2019 Booting up...
Thu Mar 21 05:03:24 UTC 2019 Booting up...
Thu Mar 21 05:03:26 UTC 2019 Booting up...
Thu Mar 21 05:03:28 UTC 2019 Booting up...
Thu Mar 21 05:03:30 UTC 2019 Booting up...
Thu Mar 21 05:03:35 UTC 2019 Booting up...
# Label은 이미지에 메타데이터를 추가한다. 이는 관리를 위한 권장사항이며, Revers-DNS 형태로 기재해야한다.
# 이미지 는 두개 이상의 라벨을 가질 수 있으며, 공백이 필요한 경우에는 따옴표와 역슬레쉬를 이용해서 이용할 수 있다.
# Label 입력시 입력 유형은 키 - 값 형태로 이루어지며, 동일한 키가 있을 경우 덮어씌워진다.

[root@docker-master ~]# docker run -l user=12345 -d redis # 컨테이너에 user 를 붙여서 실행한다.
7c181b8953c07a4ff7a214715b94e7cb3c03b67215ed21bf4d89da2cf6b41f4c
[root@docker-master ~]# echo 'user=123456' >> labels && echo 'role=cache' >> labels # 파일 형태로 만들어본다.
[root@docker-master ~]# docker run --label-file=labels -d redis # 파일로부터 해당 정보를 읽게 한다.
13dae01f656fe8e5d1bf18f6b6db51ac7c4adbc22d44f6478edf919bf4261753
# Dockerfile에서 LABEL vendor=ysyukr 로 기입하면 이미지의 vendor 레벨에 ysyukr이 입력된다.
# docker inspect 명령어로 이미지의 label을 확인할 수 있다.
# --filter 옵션으로 원하는 label이 지정된 컨테이너나, 이미지를 검색할 수 있다.
# Label은 Docker Daemon에도 적용이가능하며, 서비스와 개발의 구분을 위해서도 이용이 가능하다.
# 동일한 역할(ex: WEB)의 컨테이너들을 수평확장을 하기 위해서는 LoadBalancer가 필요하다. 이러한 역할을 하는 물리적인 장비는 대표적으로 L4라 불리는 장비들이며, 이를 소프트웨어로 구현한 것들이 LVS(Linux Virtual Server) 또는 HAProxy 같은 것들이다.
# 실제로 요 몇일 중 VM의 이중화 구성을 위해 LVS을 통한 구성을 해서 고객사에게도 해주었다.
# 컨테이너의 수평확장과 트래픽의 분배를 위해서 Nginx-Proxy를 이용해보는 것을 해볼 수 있다.
[root@docker-master ~]# docker run -d -p 80:80 -e DEFAULT_HOST=proxy.example -v /var/run/docker.sock:/tmp/docker.sock:ro --name nginx jwilder/nginx-proxy # proxy.example로 지정된 호스트로 연결되도록 설정
Unable to find image 'jwilder/nginx-proxy:latest' locally
latest: Pulling from jwilder/nginx-proxy
a5a6f2f73cd8: Pull complete 
2343eb083a4e: Pull complete 
251439d5b33c: Pull complete 
0150289a3195: Pull complete 
196dcbce1a9b: Pull complete 
8826dc3389ea: Pull complete 
c7a4bc596c6f: Pull complete 
8000a1ad9fc5: Pull complete 
3bea426c29a7: Pull complete 
8378fe8463bb: Pull complete 
Digest: sha256:619f390f49c62ece1f21dfa162fa5748e6ada15742e034fb86127e6f443b40bd
Status: Downloaded newer image for jwilder/nginx-proxy:latest
7b9637fef4836b81db3289609c88f7f161bbfef32f91a0e8f3cc6a60ec58f67f
[root@docker-master ~]# docker run -d -p 80 -e VIRTUAL_HOST=proxy.example katacoda/docker-http-server # proxy.example로 호스트를 지정해서 실행한다.
Unable to find image 'katacoda/docker-http-server:latest' locally
latest: Pulling from katacoda/docker-http-server
f139eb4721ae: Pull complete 
Digest: sha256:76dc8a47fd019f80f2a3163aba789faf55b41b2fb06397653610c754cb12d3ee
Status: Downloaded newer image for katacoda/docker-http-server:latest
2dc114622ae3e55d945983e551ffd13433a3a17a1853ca0cd6160ed5595d8767
[root@docker-master ~]# docker ps # 실행중인 컨테이너 확인
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                   NAMES
2dc114622ae3        katacoda/docker-http-server   "/app"                   31 seconds ago      Up 30 seconds       0.0.0.0:32768->80/tcp   awesome_mendeleev
7b9637fef483        jwilder/nginx-proxy           "/app/docker-entrypo…"   26 minutes ago      Up 26 minutes       0.0.0.0:80->80/tcp      nginx
[root@docker-master ~]# curl localhost # proxy.example로 연결되었는지 확인
<h1>This request was processed by host: 2dc114622ae3</h1>
[root@docker-master ~]# docker run -d -p 80 -e VIRTUAL_HOST=proxy.example katacoda/docker-http-server # 동일한 컨테이너 하나 더 실행
3617b8f0216660beab44b929ab4448fad9f98f5b34ce6d8b848ede69f190a836
[root@docker-master ~]# docker ps # 실행중인 컨테이너 확인
CONTAINER ID        IMAGE                         COMMAND                  CREATED              STATUS              PORTS                   NAMES
3617b8f02166        katacoda/docker-http-server   "/app"                   8 seconds ago        Up 8 seconds        0.0.0.0:32769->80/tcp   pedantic_minsky
2dc114622ae3        katacoda/docker-http-server   "/app"                   About a minute ago   Up About a minute   0.0.0.0:32768->80/tcp   awesome_mendeleev
7b9637fef483        jwilder/nginx-proxy           "/app/docker-entrypo…"   28 minutes ago       Up 28 minutes       0.0.0.0:80->80/tcp      nginx
[root@docker-master ~]# curl localhost # 순환되어 접속하는 것을 확인
<h1>This request was processed by host: 2dc114622ae3</h1>
[root@docker-master ~]# curl localhost # 순환되어 접속하는 것을 확인
<h1>This request was processed by host: 3617b8f02166</h1>
# Docker-Compose는 여러 컨테이너를 정의하고 운영하는데 필요한 도구다.
# docker-compose.yml 이라는 파일로 구성하며, 여기에는 컨테이너에 필요한 정보들이 기입된다.
[root@docker-master home]# vi docker-compose.yml # docker-compose.yml 을 작성한다.
web:
  build: .

  links:
    - redis

  ports:
    - "3000"
    - "8000"

redis:
  image: redis:alpine
  volumes:
    - /var/redis/data:/data
[root@docker-master home]# docker-compose up -d # 백그라운드에서 구동하도록 실행
Building web
Step 1/2 : FROM ocelotuproar/alpine-node:5.7.1-onbuild
# Executing 3 build triggers
 ---> Running in cff8c5b4e84c
scrapbook-redis-node-docker-example@0.0.0 /usr/src/app
`-- redis@0.12.1

Removing intermediate container cff8c5b4e84c
 ---> e3111d3a098a
Step 2/2 : EXPOSE 3000
 ---> Running in cea843a616b9
Removing intermediate container cea843a616b9
 ---> 97a17bc32c3f
Successfully built 97a17bc32c3f
Successfully tagged tutorial_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating tutorial_redis_1 ... done
Creating tutorial_web_1   ... done
[root@docker-master home]# docker-compose ps # compose로 실행된 컨테이너확인
      Name                    Command               State                        Ports
------------------------------------------------------------------------------------------------------------
tutorial_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
tutorial_web_1     npm start                        Up      0.0.0.0:32769->3000/tcp, 0.0.0.0:32768->8000/tcp
[root@docker-master home]# docker-compose logs # 로그 확인
Attaching to tutorial_web_1, tutorial_redis_1
web_1    |
web_1    | > scrapbook-redis-node-docker-example@0.0.0 start /usr/src/app
web_1    | > node server.js
web_1    |
web_1    | Listening on port 3001
redis_1  | 1:C 22 Mar 2019 07:32:10.043 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 22 Mar 2019 07:32:10.048 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 22 Mar 2019 07:32:10.048 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 22 Mar 2019 07:32:10.050 * Running mode=standalone, port=6379.
redis_1  | 1:M 22 Mar 2019 07:32:10.050 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 22 Mar 2019 07:32:10.050 # Server initialized
redis_1  | 1:M 22 Mar 2019 07:32:10.050 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1  | 1:M 22 Mar 2019 07:32:10.050 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 22 Mar 2019 07:32:10.050 * Ready to accept connections
[root@docker-master home]# docker-compose scale web=3 # 웹서버의 숫자 증설
WARNING: The scale command is deprecated. Use the up command with the --scale flag instead.
Starting tutorial_web_1 ... done
Creating tutorial_web_2 ... done
Creating tutorial_web_3 ... done
[root@docker-master home]#  docker-compose scale web=1 # 웹서버의 숫자 감소
WARNING: The scale command is deprecated. Use the up command with the --scale flag instead.
Stopping and removing tutorial_web_2 ... done
Stopping and removing tutorial_web_3 ... done
[root@docker-master home]# docker-compose stop # 컨테이너 중지
Stopping tutorial_web_1   ... done
Stopping tutorial_redis_1 ... done
[root@docker-master home]# docker-compose rm # 삭제
Going to remove tutorial_web_1, tutorial_redis_1
Are you sure? [yN] y
Removing tutorial_web_1   ... done
Removing tutorial_redis_1 ... done