[Docker] Keep Calm And Learn Docker Swarm
Docker Swarm ์ฌ์ฉํ๊ธฐ
- Swarm node ๊ตฌ์ฑ ๊ณํ
- Swarm ๊ตฌ์ฑํ๊ธฐ
- Docker private registry ๊ตฌ์ถํ๊ธฐ
- Stack / Service ์คํ
- Deploy๋ฅผ ์ํ Compose file ์์ฑํ๊ธฐ
- Portainer ์ค์นํ๊ธฐ
1. Swarm node ๊ตฌ์ฑ ๊ณํ
ํ ์คํธ์ฉ Swarm node ๊ตฌ์ฑ
- book server (manager node) / 192.168.101.30
- samsung notebook (worker node) / 192.168.100.46
- msi notebook (worker node) / 192.168.100.47
ํ๋ก๋ํธ์ฉ Swarm node ๊ตฌ์ฑ
- app server (manager node) / 192.168.101.80
- api server (worker node) / 192.168.101.70
- web server (worker node) / 192.168.101.100
์๋ ๋๊ฐ์ง์ Error ๋ฉ์์ง๋ฅผ ๋ณด์ง ์๊ธฐ ์ํด ํด์ผ ํ ์ผ
"swarm node is missing network attachments, ip addresses may be exhausted."
"failed to allocate gateway (10.0.1.1): Address already in use."
1. Hostname ์ค์
$ sudo hostnamectl status
$ sudo hostnamectl set-hostname ITS-APISERVER.ITSROOM.COM
$ sudo hostnamectl set-hostname ITS-APPSERVER.ITSROOM.COM
$ sudo hostnamectl set-hostname ITS-WEBSERVER.ITSROOM.COM
$ sudo reboot
2. Docker Swarm Routing Mesh(Ingress network) ์ค์
- Check port open
- Port 7946 TCP/UDP for container network discovery.
- Port 4789 UDP for the container ingress network.
# netstat -tnl
# netstat -unl
# firewall-cmd --zone=public --list-all
# firewall-cmd --zone=public --permanent --add-port=7946/tcp
# firewall-cmd --zone=public --permanent --add-port=7946/udp
# firewall-cmd --zone=public --permanent --add-port=4789/udp
# firewall-cmd --reload
# firewall-cmd --zone=public --list-all
์ฐธ์กฐ ๋ธ๋ก๊ทธ https://subicura.com/2017/02/25/container-orchestration-with-docker-swarm.html
2. Swarm ๊ตฌ์ฑํ๊ธฐ
docker, docker-compose ์ค์น ํ์
- centos์ docker ์ค์น https://docs.docker.com/engine/install/centos/
Swarm init (Swarm ๊ตฌ์ถ): manager node์์ ์คํ
- input
[root@ITS-WEBSERVER its]# docker swarm init --advertise-addr 192.168.101.80
- output(worker node์์ ์คํํ join-token ๋ช
๋ น์ด)
Swarm initialized: current node (j047o4z6w71zwolmvaitbkb6e) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-2v3sdrfzc6mkr310wqseoq1cevwkxupqldozhhzxa8jd4d8mmy-6c27bitjryr39a7wzr6j8ik1o \
192.168.101.80:2377
- (manager node์ถ๊ฐ๋ฅผ ์ํ join-token ๋ช
๋ น์ด)
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
node list ํ์ธ - node ๊ตฌ์ถ์ด ์ ๋์๋์ง ํ์ธ
- input
[root@ITS-WEBSERVER its]# docker node ls
- output
ID HOSTNAME STATUS ENGINE VERSION
nhyjv7tmnvzwe92fszb238dtm * localhost.localdomain Ready 19.03.8
manager node ์์ ๋ฐฉํ๋ฒฝ ์ค์
- input
[root@ITS-WEBSERVER its]# firewall-cmd --zone=public --permanent --add-port=2377/tcp
[root@ITS-WEBSERVER its]# firewall-cmd --reload
[root@ITS-WEBSERVER its]# firewall-cmd --zone=public --list-all
worker node์์ join command ์คํํ๊ธฐ
- input
[root@ITS-WEBSERVER its]# docker swarm join --token SWMTKN-1-1nkn5ygrdfrcjoowntchb8djsh1ufski1g4805y9b8s1odgp3r-1mcdbhcg831w57bvv25u9wdoy 192.168.101.30:2377
- output
This node joined a swarm as a worker.
- ๋ฐฉํ๋ฒฝ ์ค์ ํ์ง ์์ ๋ ๋ฐ์ํ๋ Error
- output
-> error
Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp 192.168.101.30:2377: connect: no route to host"
manager node์์ node list ํ์ธ
- input
[root@ITS-WEBSERVER its]# docker node ls
- output
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
063cxgv750ue99jcnxl1xljxx its-apiserver.itsroom.com Ready Active
84yzzxr8fqyvi22jh9u4dlfsh its-uyeg-webserver.itsroom.com Ready Active
w197c4yqd6kyyriv3p552upm8 * ITS-WEBSERVER.ITSROOM.COM Ready Active Leader
- 80๋ฒ ์๋ฒ์ hostname์ด ์ด๋ฏธ webserver๋ก ์ค์ ๋์ด ์์ด 100๋ฒ ์๋ฒ์ hostname์ it-uyeg-webserver๋ก ์ค์ ํจ.
tip: manager node์์ join ๋ช ๋ น์ด ๊ฒ์ํ๋ ๋ฐฉ๋ฒ
[root@ITS-WEBSERVER its]# docker swarm join-token manager
[root@ITS-WEBSERVER its]# docker swarm join-token worker
- Docker๋ ๊ณ ๊ฐ์ฉ์ฑ์ ๊ตฌํํ๊ธฐ ์ํด ํด๋ฌ์คํฐ ๋น 3 ๊ฐ ๋๋ 5 ๊ฐ์ ๊ด๋ฆฌ์ ๋ ธ๋๋ฅผ ๊ถ์ฅํฉ๋๋ค. ์ค์ ๋ชจ๋ ๊ด๋ฆฌ์ ๋ ธ๋๋ Raft๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๋ฏ๋ก ํ์์ ๊ด๋ฆฌ์๊ฐ ์์ด์ผํฉ๋๋ค. ๊ด๋ฆฌ์ ๋ ธ๋์ ์ ๋ฐ ์ด์์ด ์ฌ์ฉ ๊ฐ๋ฅํ ํ ์์ ๊ณ์ ์๋ ํ ์ ์์ต๋๋ค.
tip: Node์์ ์ ๊ฑฐ
- Worker node์์ Leave Swarm ๋ช ๋ น์ด ์คํ
[root@ITS-WEBSERVER its]# docker swarm leave
Node left the swarm.
- Manager node์์ Remove Node ๋ช ๋ น์ด ์คํ
[root@ITS-WEBSERVER its]# docker node rm node-2
3. Docker private registry ๊ตฌ์ถํ๊ธฐ
Docker registry๋ฅผ ์ํ port ๋ฐฉํ๋ฒฝ ์ค์
# firewall-cmd --zone=public --permanent --add-port=5000/tdp
# firewall-cmd --reload
# firewall-cmd --zone=public --list-all
โNo such image: ~โ ์ ๊ฐ์ Error ๋ฐ์ํ๋ ๊ฒ์ ํด๊ฒฐํ๊ธฐ ์ํ private registry ์์ฑ
- Docker registry ์ค์น
<์ฐธ์กฐ: https://novemberde.github.io/2017/04/09/Docker_Registry_0.html>
VOLUME ๊ถํ์ ์ํ ๋ช ๋ น์ด
chmod a+rw /var/run/docker.sock
chmod 777 /home/its/data/docker (์ ์ฅ์์น)
registry ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค๊ธฐ (์ํด๋ ์๊ด ์์)
$ docker pull registry
registry๋ฅผ ์คํํ๊ธฐ
$ docker run -d \
-p 5000:5000 \
--restart=always \
--privileged \
--name docker-registry \
-e REGISTRY_STORAGE_DELETE_ENABLED=true \
-v /home/its/data:/var/lib/registry \
registry:2
- docker registry์์ image ์ญ์ ๋ฅผ ์ํ ํ๊ฒฝ์ค์ ๋ช ๋ น์ด
-e REGISTRY_STORAGE_DELETE_ENABLED=true
- docker registry ์ volume ์ค์ ์ ์ํ ๋ช ๋ น์ด
-v /home/its/data:/var/lib/registry
- Registry ์ image push ํ๊ธฐ pullํ๊ธฐ
hello-world ์ด๋ฏธ์ง๊ฐ ์์ผ๋ docker hub์์ pullํ์.
$ docker pull hello-world
localhost/hello-world ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค์ด๋ณด์.
$ docker tag hello-world localhost:5000/hello-world
์ด๋ฏธ์ง pushํ๊ธฐ
$ docker push localhost:5000/hello-world
์ด๋ฏธ์ง ํ์ธํ๊ธฐ
$ curl -X GET http://localhost:5000/v2/_catalog
# ์ถ๋ ฅ {"repositories":["hello-world"]}
ํ๊ทธ ์ ๋ณด ํ์ธํ๊ธฐ
$ curl -X GET http://localhost:5000/v2/hello-world/tags/list
# ์ถ๋ ฅ {"name":"hello-world","tags":["latest"]}
<์ฐธ์กฐ: https://waspro.tistory.com/532>
โserver gave HTTP response to HTTPS clientโ ๋ผ๋ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด daemon.json ํ์ผ์ ์์
$ vi /etc/docker/daemon.json
{
"insecure-registries": ["192.168.101.70:5000"]
}
์ฌ์คํ
$ systemctl daemon-reload
$ systemctl restart docker
docker registry๋ก ๋ถํฐ image pull ํ๊ธฐ
$ docker pull 192.168.101.70:5000/test:latest
latest: Pulling from 192.168.101.70:5000/test
68ced04f60ab: Already exists
c4039fd85dcc: Already exists
c16ce02d3d61: Already exists
7469e3cf55fe: Pull complete
Digest: sha256:335079834819530f9746329187a4c26a011ea3f74d4b607106e3d2fbd339d273
Status: Downloaded newer image for 192.168.101.70:5000/test:latest
Docker registry์์ image ์ญ์ ํ๊ธฐ
<์ฐธ์กฐ: https://stackoverflow.com/questions/25436742/how-to-delete-images-from-a-private-docker-registry>
- to delete an image, you should run the registry container with REGISTRY_STORAGE_DELETE_ENABLED=true parameter.
- I set โdelete: enabledโ value to true in /etc/docker/registry/config.yml file. For this configuration no need to set REGISTRY_STORAGE_DELETE_ENABLED variable
digest ํ์ธ์ ์ํ ๋ช ๋ น์ด
[root@its-apiserver its]# curl -k -I -H Accept:\* http://localhost:5000/v2/test/manifests/latest
HTTP/1.1 200 OK
Content-Length: 12076
Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
Docker-Content-Digest: sha256:e034004b3d20f3a95d0dabd48aece8b5db1eaa2bc6d9b02163e5434c7013eb0a
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:e034004b3d20f3a95d0dabd48aece8b5db1eaa2bc6d9b02163e5434c7013eb0a"
X-Content-Type-Options: nosniff
Date: Mon, 06 Apr 2020 08:36:04 GMT
Delete ๋ช ๋ น์ด ํ ์คํธ(์๋ฌ ๋ฉ์์ง ๋ฐ์)
[root@its-apiserver its]# curl -X DELETE http://localhost:5000/v2/test/manifests/latest
{"errors":[{"code":"DIGEST_INVALID","message":"provided digest did not match uploaded content"}]}
[root@its-apiserver its]# curl -X DELETE http://localhost:5000/v2/test/manifests/sha256:e034004b3d20f3a95d0dabd48aece8b5db1eaa2bc6d9b02163e5434c7013eb0a
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown"}]}
docker registry๋ฅผ ์ํ ๊ฐ์ข ๋ช ๋ น์ด
01. registry ๋ด๋ถ์ repository ์ ๋ณด ์กฐํ
$ curl -X GET <REGISTRY URL:ํฌํธ>/v2/_catalog
02. repository ์ ๋ํ์ฌ tag ์ ๋ณด ์กฐํ
$ curl -X GET <REGISTRY URL:ํฌํธ>/v2/<REPOSITORY ์ด๋ฆ>/tags/list
03. content digest ์กฐํ
$ curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://<REGISTRY URL:ํฌํธ>/v2/<REPOSITORY ์ด๋ฆ>/manifests/<TAG ์ด๋ฆ> 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'
04. manifest ์ญ์
$ curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://<REGISTRY URL:ํฌํธ>/v2/<REPOSITORY ์ด๋ฆ>/manifests/<DIGEST ์ ๋ณด>
05. GC(Garbage Collection)
$ docker exec -it docker-registry registry garbage-collect /etc/docker/registry/config.yml
์ถ์ฒ: https://trylhc.tistory.com/entry/Docker-registry-์ญ์ -2 [์ค๋์ฒ๋ผ..?]
4. Stack / Service ์คํ
Source download
- git clone API_Server
- Compose build ๋ช ๋ น์ด๋ฅผ ํตํด image ์์ฑํ๊ธฐ
[root@ITS-WEBSERVER its]# docker-compose build
- Tagging and Pushing
- tag
[root@bookserver API_Server]# docker tag api_server_gateway 192.168.101.70:5000/api_server_gateway
[root@bookserver API_Server]# docker tag api_server_standalone 192.168.101.70:5000/api_server_standalone
[root@bookserver API_Server]# docker tag api_server_nginx2 192.168.101.70:5000/api_server_nginx2
[root@bookserver API_Server]# docker tag app_server_mobile 192.168.101.70:5000/app_server_mobile
[root@bookserver API_Server]# docker tag app_server_nginx1 192.168.101.70:5000/app_server_nginx1
[root@bookserver API_Server]# docker tag app_server_indexing 192.168.101.70:5000/app_server_indexing
[root@bookserver API_Server]# docker tag app_server_set 192.168.101.70:5000/app_server_set
[root@bookserver API_Server]# docker tag app_server_web 192.168.101.70:5000/app_server_web
- push
[root@bookserver API_Server]# docker push 192.168.101.70:5000/api_server_gateway
[root@bookserver API_Server]# docker push 192.168.101.70:5000/api_server_standalone
[root@bookserver API_Server]# docker push 192.168.101.70:5000/api_server_nginx2
[root@bookserver API_Server]# docker push 192.168.101.70:5000/app_server_mobile
[root@bookserver API_Server]# docker push 192.168.101.70:5000/app_server_nginx1
[root@bookserver API_Server]# docker push 192.168.101.70:5000/app_server_indexing
[root@bookserver API_Server]# docker push 192.168.101.70:5000/app_server_set
[root@bookserver API_Server]# docker push 192.168.101.70:5000/app_server_web
- image ์ ๋ฌด ํ์ธ
[root@bookserver API_Server]# curl -X GET http://192.168.101.70:5000/v2/_catalog
{"repositories":["api_server_gateway","api_server_nginx_swarm","api_server_standalone","app_server_indexing","app_server_mobile","app_server_nginx_swarm","app_server_set","app_server_web"]}
- Deploy API Server
- Nginx
- Gateway (bm4server)
- StandAlone (bm3server)
- input
[root@bookserver API_Server]# docker stack deploy --compose-file docker-compose.yml api_server
- output
Ignoring unsupported options: build, restart
Ignoring deprecated options:
container_name: Setting the container name is not supported.
Creating network api_server_backend
Creating service api_server_nginx
Creating service api_server_gateway
Creating service api_server_standalone
- Test -Stack deploy MariaDB
[root@bookserver mariadb-docker]# docker stack deploy -c docker-compose.yml mariadb1
Creating service mariadb1_mariadb
5. Deploy๋ฅผ ์ํ Compose file ์์ฑํ๊ธฐ
- api server ymlํ์ผ ๋น๊ต
- ๊ธฐ์กด compose ํ์ผ
version: "3"
services:
nginx:
container_name: nginx
build:
context: ./nginx
dockerfile: ./Dockerfile
ports:
- "8083:8083"
restart: always
networks:
- backend
depends_on:
- gateway
- standalone
gateway:
container_name: bm4server
build:
context: ./gatewayAPI
dockerfile: ./Dockerfile
ports:
- "9210:9210"
restart: always
networks:
- backend
standalone:
container_name: bm3server
build:
context: ./standAloneAPI
dockerfile: ./Dockerfile
ports:
- "9211:9211"
restart: always
networks:
- backend
networks: # ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ bridge ๋คํธ์ํฌ
backend:
driver: bridge
- deploy ์ฉ yml ํ์ผ
version: "3"
services:
nginx2:
container_name: nginx_swarm
image: api_server_nginx_swarm
build:
context: ./nginx
dockerfile: ./Dockerfile
ports:
- "8083:8083"
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- frontend
- backend
depends_on:
- gateway
- standalone
gateway:
container_name: bm4server
image: api_server_gateway
build:
context: ./gatewayAPI
dockerfile: ./Dockerfile
ports:
- "9210:9210"
restart: always
networks:
- backend
standalone:
container_name: bm3server
image: api_server_standalone
build:
context: ./standAloneAPI
dockerfile: ./Dockerfile
ports:
- "9211:9211"
restart: always
networks:
- backend
networks:
backend:
frontend:
6. Portainer ์ค์นํ๊ธฐ
- ref: https://help.iwinv.kr/manual/read.html?idx=548
docker volume create portainer_data
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --restart=always portainer/portainer
-- for gitlab server --
docker run -d -p 9009:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --restart=always portainer/portainer
7. Registry UI ์ค์น
- https://waspro.tistory.com/532
- Dockerfile ์์ฑ
[root@ITS-WEBSERVER docker-registry-web]# cat config.yaml
registry:
# ๊ธฐ์กด์ ์ค์นํ docker private registry
url: http://192.168.101.70:5000/v2
# Docker registry name
name: 192.168.101.70:5000
# docker ๊ถํ ๋ถ์ฌ
readonly: false
auth:
enabled: false
[root@ITS-WEBSERVER docker-registry-web]#
- docker-registry-web ์คํ
[root@ITS-WEBSERVER docker-registry-web]# docker run -it -d -p 8080:8080 --name registry-web -v /home/its/docker-registry-web/config.yaml:/conf/config.yml:ro hyper/docker-registry-web
Unable to find image 'hyper/docker-registry-web:latest' locally
Trying to pull repository docker.io/hyper/docker-registry-web ...
latest: Pulling from docker.io/hyper/docker-registry-web
04c996abc244: Pull complete
d394d3da86fe: Pull complete
bac77aae22d4: Pull complete
b48b86b78e97: Pull complete
09b3dd842bf5: Pull complete
69f4c5394729: Pull complete
b012980650e9: Pull complete
7c7921c6fda1: Pull complete
e20331c175ea: Pull complete
40d5e82892a5: Pull complete
a414fa9c865a: Pull complete
0304ae3409f3: Pull complete
13effc1a664f: Pull complete
e5628d0e6f8c: Pull complete
0b0e130a3a52: Pull complete
d0c73ab65cd2: Pull complete
240c0b145309: Pull complete
f1fd6f874e5e: Pull complete
40b5e021928e: Pull complete
88a8c7267fbc: Pull complete
f9371a03010e: Pull complete
Digest: sha256:723ffa29aed2c51417d8bd32ac93a1cd0e7ef857a0099c1e1d7593c09f7910ae
Status: Downloaded newer image for docker.io/hyper/docker-registry-web:latest
79a564384a12020a94ce09a84497c82245706f8abb3622554b43b474d2706f71
- ์ ์
- http://192.168.101.80:8080/