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

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

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

진행한 강의 목록

  • Communicating Between Containers
  • Creating Networks Between Containers using Networks
  • Persisting Data Using Volumes
  • Managing Log Files

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

구성환경

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

내용 정리 컨테이너간 연결에는 데이터 컨테이너를 생성해서 연결할 수도 있다. 데이터 컨테이너는 저장소를 연결하는 것이며, 컨테이너간 데이터 교환을 위해서는 링크를 설정하거나, 네트워크를 설정할 수 있다.

# Link를 통한 컨테이너간 연결을 진행해보자.
[root@docker-master ~]# docker run -d --name redis-A redis # redis를 테스트로 실행한다.
18f98193b4a8202584503a8f095097d6a94828a63bc7fdcce01ca7575eafa4f3
[root@docker-master ~]# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
18f98193b4a8        redis                  "docker-entrypoint.s…"   4 seconds ago       Up 3 seconds        6379/tcp            redis-A
[root@docker-master ~]# docker run --link redis-A:redis alpine env # 컨테이너간 링크를 위해 컨테이너 환경 확인
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
8e402f1a9c57: Already exists 
Digest: sha256:644fcb1a676b5165371437feaa922943aaf7afcfa8bfee4472f6860aad1ef2a0
Status: Downloaded newer image for alpine:latest
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0004521b1833
REDIS_PORT=tcp://172.17.0.2:6379
REDIS_PORT_6379_TCP=tcp://172.17.0.2:6379
REDIS_PORT_6379_TCP_ADDR=172.17.0.2
REDIS_PORT_6379_TCP_PORT=6379
REDIS_PORT_6379_TCP_PROTO=tcp
REDIS_NAME=/sad_snyder/redis
REDIS_ENV_GOSU_VERSION=1.10
REDIS_ENV_REDIS_VERSION=5.0.4
REDIS_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.4.tar.gz
REDIS_ENV_REDIS_DOWNLOAD_SHA=3ce9ceff5a23f60913e1573f6dfcd4aa53b42d4a2789e28fa53ec2bd28c987dd
HOME=/root
[root@docker-master ~]# docker run --link redis-A:redis alpine cat /etc/hosts # 컨테이너 내 hosts 설정 확인
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      redis 18f98193b4a8 redis-A
172.17.0.3      9c16f1b4e823
[root@docker-master ~]# docker run --link redis-A:redis alpine ping -c 5 redis # 컨테이너에서 Ping 테스트
PING redis (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.085 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: seq=4 ttl=64 time=0.059 ms

--- redis ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.049/0.061/0.085 ms
[root@docker-master ~]# docker run -d -p3000:3000 --link redis-A:redis katacoda/redis-node-docker-example # redis와 node를 link로 연결해보자.
Unable to find image 'katacoda/redis-node-docker-example:latest' locally
latest: Pulling from katacoda/redis-node-docker-example
12b41071e6ce: Pull complete 
a3ed95caeb02: Pull complete 
49a025abf7e3: Pull complete 
1fb1c0be01ab: Pull complete 
ae8c1f781cde: Pull complete 
db73207ad2ae: Pull complete 
446b13034c13: Pull complete 
Digest: sha256:1aae9759464f00953c8e078a0e0d0649622fef9dd5655b1491f9ee589ae904b4
Status: Downloaded newer image for katacoda/redis-node-docker-example:latest
cbc0a8b7eb0a20afa76afe3260b21992fd7249067f4adc9e71bbdf371ab87a79
[root@docker-master ~]# curl localhost:3000 # 연결 확인
This page was generated after talking to redis.

Application Build: 1

Total requests: 1

IP count: 
    ::ffff:172.17.0.1: 1
# 네트워크로 컨테이너간 연결을 해보자
[root@docker-master ~]# docker network create ysyukr-network # 컨테이너 연결용 네트워크를 생성한다.
a0d77a58712c1d93d9ea6d68cfa197185dde4d5cd9b38fb7fbe7d637e57ca5c7
[root@docker-master ~]# docker network ls # docker 네트워크 목록을 확인해본다.
NETWORK ID          NAME                DRIVER              SCOPE
94258abc87ca        bridge              bridge              local
133ecc60de6b        docker_gwbridge     bridge              local
8e6d20245102        host                host                local
18cf64c74806        none                null                local
a0d77a58712c        ysyukr-network      bridge              local
[root@docker-master ~]# docker run -d --name=redis --net=ysyukr-network redis # 만만한 redis로 앞서 생성한 네트워크에 연결해서 실행하도록 한다.
74d7d500cf80f300aa8717325c2a3d531dad4493b54eefad46c6b2d8873035d7
[root@docker-master ~]# docker run --net=ysyukr-network alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=9d6a511ce8d4
HOME=/root
[root@docker-master ~]# docker run --net=ysyukr-network alpine cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.3      4d13701bcd51
[root@docker-master ~]# docker run --net=ysyukr-network alpine cat /etc/resolv.conf 
search docker-master
nameserver 127.0.0.11
options ndots:0
[root@docker-master ~]# docker run --net=ysyukr-network alpine ping -c5 redis
PING redis (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.100 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.057 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.058 ms
64 bytes from 172.19.0.2: seq=3 ttl=64 time=0.062 ms
64 bytes from 172.19.0.2: seq=4 ttl=64 time=0.064 ms

--- redis ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.057/0.068/0.100 ms
# 컨테이너에 2개의 네트워크를 연결해보자
[root@docker-master ~]# docker network create ysyukr2-network # 2번째 네트워크 생성
a7f9a6d2a6b5ef670472392aa567fd9d8e4c77bc0583c04493d91d4008025308
[root@docker-master ~]# docker network connect ysyukr2-network redis # 앞서 생성한 redis에 연결
[root@docker-master ~]# docker run -d -p 3000:3000 --net=ysyukr2-network katacoda/ redis-node-docker-example #node와 연결하도록 컨테이너 생성
e9cfe207d590a1c1eb4fbad84627808806791533b696e1eecbd163f643cf27bd
[root@docker-master ~]# curl localhost:3000 # 연결 테스트
This page was generated after talking to redis.

Application Build: 1

Total requests: 1

IP count: 
    ::ffff:172.20.0.1: 1
# 별칭을 통한 네트워크 연결
[root@docker-master ~]# docker network create ysyukr3-network # 3번째 네트워크 생성
76dfde3dd1348d929465f487bd338b1cc3fe84b09a8c258f8cf3e46ec837d85b
[root@docker-master ~]# docker network connect --alias db ysyukr3-network redis # 앞서 생성한 redis로  별칭으로 연결
[root@docker-master ~]# docker run --net=ysyukr3-network alpine ping -c3 db # # 별칭으로 테스트
PING db (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.063 ms
64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.061 ms
64 bytes from 172.21.0.2: seq=2 ttl=64 time=0.065 ms

--- db ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.061/0.063/0.065 ms
# 컨테이너에서 네트워크를 끊어보자
[root@docker-master ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
94258abc87ca        bridge              bridge              local
133ecc60de6b        docker_gwbridge     bridge              local
8e6d20245102        host                host                local
18cf64c74806        none                null                local
a7f9a6d2a6b5        ysyukr2-network     bridge              local
76dfde3dd134        ysyukr3-network     bridge              local
a0d77a58712c        ysyukr-network      bridge              local
# Docker 네트워크의 상세내역 확인
[root@docker-master ~]# docker network inspect ysyukr-network # inspect 옵션을 통해 네트워크에 구성된 내용이 확인 가능하다.
[
    {
        "Name": "ysyukr-network",
        "Id": "a0d77a58712c1d93d9ea6d68cfa197185dde4d5cd9b38fb7fbe7d637e57ca5c7",
        "Created": "2019-03-21T10:07:28.102523805+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "74d7d500cf80f300aa8717325c2a3d531dad4493b54eefad46c6b2d8873035d7": {
                "Name": "redis",
                "EndpointID": "d9321e8f7395fe78153006500d4ae7ecd67b719efe3c397b272a2b96a2f622c5",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
     }
]
[root@docker-master ~]# docker network disconnect ysyukr-network redis # ysyukr-network에서 redis를 분리한다.
[root@docker-master ~]# docker network inspect ysyukr-network # ysyukr-network의 상세내용을 통해  분리가 되었는지 확인한다.
[
    {
        "Name": "ysyukr-network",
        "Id": "a0d77a58712c1d93d9ea6d68cfa197185dde4d5cd9b38fb7fbe7d637e57ca5c7",
        "Created": "2019-03-21T10:07:28.102523805+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
# Docker 볼륨을 이용해서 데이터를 유지하는 방법이다.
[root@docker-master ~]# docker run -v /docker/redis/:/data --name r1 -d redis redis-server --appendonly yes # -v를 이용해서 로컬의 /docker/redis 에서 컨테이너 내 /data로 연결한다
68ebdc208e29a03cd21e402939cd68c738e99fb066711d643ca3b6049518c202
[root@docker-master ~]# cat data | docker exec -i r1 redis-cli --pipe 
cat: data: 그런 파일이나 디렉터리가 없습니다
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 0
[root@docker-master ~]# ls /docker/redis/ # 로컬 폴더 확인
appendonly.aof
[root@docker-master ~]# docker run -v /docker/redis:/backup ubuntu ls /backup # ubuntu 인스턴스에서 redis 파일을 확인할 수 있도록 마운트 하고 ls로 확인
appendonly.aof
[root@docker-master ~]# docker run --volumes-from r1 -it ubuntu ls /data # redis의 /data 볼륨을 ubuntu 의 /data로 연결하고 목록을 확인한다.
appendonly.aof
[root@docker-master ~]# docker run -v /docker/redis:/data:ro -it ubuntu rm -rf /data # ubuntu 인스턴스에서 /data를 마운트 하지만, read-only로 하고, 테스트로 삭제를 진행하는 명령어
rm: cannot remove '/data/appendonly.aof': Read-only file system
# 컨테이너의 로그 관리방법
[root@docker-master ~]# docker run -d --name redis redis # 테스트용 redis를 하나 띄운다.
6d5647976c1b214f4d15e191560dc177804569f6a17223ad5f9148dff55dbf57
[root@docker-master ~]# docker logs redis # 컨테이너의 로그를 읽어온다.
1:C 21 Mar 2019 04:41:47.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 21 Mar 2019 04:41:47.490 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 21 Mar 2019 04:41:47.490 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 21 Mar 2019 04:41:47.491 * Running mode=standalone, port=6379.
1:M 21 Mar 2019 04:41:47.491 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 21 Mar 2019 04:41:47.491 # Server initialized
1:M 21 Mar 2019 04:41:47.491 # 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.
1:M 21 Mar 2019 04:41:47.491 * Ready to accept connections
[root@docker-master ~]# docker run -d --name=redis-sys --log-driver=syslog redis # Host의 Syslog에 컨테이너 로그를 기록하게 한다.
baf282e20f2ef10d87835f4ce40ce79c7af638f5024b1a8e63f10ca89299b49c
[root@docker-master ~]# vi /var/log/messages # host의 syslog 확인시에 나오는 로그
.....
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:C 21 Mar 2019 04:43:22.279 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:C 21 Mar 2019 04:43:22.279 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:C 21 Mar 2019 04:43:22.279 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:M 21 Mar 2019 04:43:22.280 * Running mode=standalone, port=6379.
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:M 21 Mar 2019 04:43:22.280 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower valueof 128.
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:M 21 Mar 2019 04:43:22.280 # Server initialized
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:M 21 Mar 2019 04:43:22.280 # 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.
Mar 21 13:43:22 docker-master baf282e20f2e[35739]: 1:M 21 Mar 2019 04:43:22.280 * Ready to accept connections
[root@docker-master ~]# docker run -d --name redis-none --log-driver=none redis # 컨테이너의 로그를 기록하지 않도록 설정
73bcb0794de9e857660fc90a69c7355abb4a44e83c30487c0c49138556dc9f6e
[root@docker-master ~]# docker logs redis-none # 확인시 로그가 기록되지 않는다.
Error response from daemon: configured logging driver does not support reading
[root@docker-master ~]# docker inspect --format '{{ .HostConfig.LogConfig }}' redis # 기록되는 로그의 유형을 확인할 수 있다.
{json-file map[]}
[root@docker-master ~]# docker inspect --format '{{ .HostConfig.LogConfig }}' redis-sys
{syslog map[]}
[root@docker-master ~]# docker inspect --format '{{ .HostConfig.LogConfig }}' redis-none
{none map[]}