이 포스트는 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