멀티 컨테이너를 한 번에 실행시키기

bridge라고 명명되어있지만 실제로 inspect 해 보면 docker0임을 알 수 있다.
가상 스위치 역할을 하고 있다.
볼륨, 네트워크 만들기
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
[root@localhost ~]# docker volume create my-vol01
my-vol01
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local my-vol01
[root@localhost ~]# docker inspect my-vol1
[]
Error: No such object: my-vol1
[root@localhost ~]# docker inspect my-vol01
[
{
"CreatedAt": "2022-07-13T09:47:02+09:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol01/_data",
"Name": "my-vol01",
"Options": {},
"Scope": "local"
}
]
[root@localhost ~]# docker network create new-net --subnet 10.29.0.0/16 --ip-range 10.29.0.0/20 --gateway 10.29.0.1
4b2a1eed61fa6b5fff306abd627d1f7c20f23778d5c76547bfdfab8440625f63
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
87d1cf407e41 bridge bridge local
186c1a480a84 host host local
4b2a1eed61fa new-net bridge local
18b184ac7281 none null local
[root@localhost ~]# docker inspect new-net
[
{
"Name": "new-net",
"Id": "4b2a1eed61fa6b5fff306abd627d1f7c20f23778d5c76547bfdfab8440625f63",
"Created": "2022-07-13T10:05:50.392799225+09:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "10.29.0.0/16",
"IPRange": "10.29.0.0/20",
"Gateway": "10.29.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
onbuild 디렉터리를 만든 후 Dockerfile.base을 만든다.
vi Dockerfile.base //웹베이스가 될 파일
FROM ubuntu:18.04
RUN sed -i 's/archive.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/sources.list
RUN apt-get -y update
RUN apt-get -y install nginx
EXPOSE 80
ONBUILD ADD website*.tar /var/www/html/
CMD ["nginx", "-g", "daemon off;"]
[root@localhost onbuild]# docker build -t hyun141/web-site:v2.0 -f Dockerfile.base .
Sending build context to Docker daemon 2.048kB
Step 1/7 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
09db6f815738: Pull complete
Digest: sha256:478caf1bec1afd54a58435ec681c8755883b7eb843a8630091890130b15a79af
Status: Downloaded newer image for ubuntu:18.04
---> ad080923604a
Step 2/7 : RUN sed -i 's/archive.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/sources.list
---> Running in e32229203ebd
Removing intermediate container e32229203ebd
---> 2fff28fb3a43
Step 3/7 : RUN apt-get -y update
Dockerfile이 아닌 Dockerfile.base 이므로 -f 옵션을 이용해 파일 이름을 부여한다.

[root@localhost onbuild]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have Docker ID, head over to https://hub.docker.com to create one.
Username: hyun141
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@localhost onbuild]# docker push hyun141/web-site:v2.0
The push refers to repository [docker.io/hyun141/web-base]
26b72ab37725: Pushed
655f734d89b3: Pushed
a7e3b8e4e845: Pushed
95129a5fe07e: Mounted from library/ubuntu
2.0: digest: sha256:7d98712ab93f8466ac061a2ecc83d41f0c91627a590a63c6f0c7f5b896e6cfac ize: 1160
login 후 push한다.
개발자 side
vi Dockerfile
FROM hyun141/web-site:v2.0
그리고 website.tar 파일을 다운로드 받아서 onbuild디렉터리에 둔다.
webstie.tar 파일과 Dockerfile이 같은 디렉터리에 있어야 한다.
[root@localhost onbuild]# docker build -t hyun141/web-site:v2.0 .
Sending build context to Docker daemon 6.852MB
Step 1/1 : FROM hyun141/web-base:v2.0
# Executing 1 build trigger
---> e26879f9237b
Successfully built e26879f9237b
Successfully tagged halilinux/web-base:v2.0
[root@localhost onbuild]# docker run -d -p 80:80 --name=web-site hyun141/web-site:v2.0
6edbb387e09c4e07753fda6a4100b28e6f16f2db24cb11c218b6eba9fce4a84b
[root@localhost onbuild]# docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@localhost onbuild]# docker push hyun141/web-site:v2.0
The push refers to repository [docker.io/hyun141/web-base]
26b72ab37725: Layer already exists
655f734d89b3: Layer already exists
a7e3b8e4e845: Layer already exists
95129a5fe07e: Layer already exists
v2.0: digest: sha256:7d98712ab93f8466ac061a2ecc83d41f0c91627a590a63c6f0c7f5b896e6cfac size: 1160

Dockerhub 사이트에 들어가보면
버전업 되어있다.
AWS EC2 도커 설치하기
EC2 인스턴스를 생성한다.
서브넷 - public 2a
보안 그룹- MY-SG-WEB(TCP 포트 5000번이 Open되어야 한다)
User Data Script
#!/bin/bash
sudo amazon-linux-extras install docker -y
sudo systemctl start docker && systemctl enable docker
curl https://raw.githubusercontent.com/docker/docker-ce/master/components/cli/contrib/completion/bash/docker -o /etc/bash_completion.d/docker.sh
sudo usermod -a -G docker ec2-user
docker run -d -p 80:80 --name=test-site hyun141/web-site:v2.0
docker run -d -p 5000:5000 --restart=always --name private-docker-registry registry
docker run ~ 마지막 두 줄을 추가해서 터미널에 액세스하지 않고 바로 run하도록 한다.

Route53에서 내가 만든 도메인 네임에 들어간 뒤,
어제 만든 레코드 - docker의 ip를 방금 만든 인스턴스의 ip로 수정한다.
vi /etc/docker/daemon.json
{ "insecure-registries":["docker.cloudywinter.shop:5000"] }
systemctl restart docker
시스템데몬을 재시작한다.
[root@localhost onbuild]# docker tag hyun141/web-site:v2.0 docker.cloudywinter.shop:5000/web-site:v2.0
[root@localhost onbuild]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
halilinux/web-site v2.0 e26879f9237b 32 minutes ago 172MB
docker.cloudywinter.shop:5000/web-base v2.0 337b9a3456d8 48 minutes ago 165MB
hyun141/web-base 2.0 337b9a3456d8 48 minutes ago 165MB
hyun141/web-base v2.0 337b9a3456d8 48 minutes ago 165MB
ubuntu 18.04 ad080923604a 5 weeks ago 63.1MB
[root@localhost onbuild]# docker push docker.cloudywinter.shop:5000/web-site:v2.0
The push refers to repository [docker.cloudywinter.shop:5000/web-site]
26b72ab37725: Pushing 37.6MB/60.28MB
655f734d89b3: Pushed
a7e3b8e4e845: Pushing 5.632kB
95129a5fe07e: Pushed

Docker 컴포즈
다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구. yaml파일에 쓰인 스크립트에 기반하여 동작한다.
여러 도커 컨테이너를 동시에 생성할 수 있다. 위 기능은 쿠버네티스로 대체할 수 있다.
Docker-compose 명령어를 실행하려면 yml파일이 있는 디렉터리에서 실행해야 한다.
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
mkdir my_wordpress && cd $_
vi docker-compose.yml
version: "3.3"
services: #컨테이너들을 일컫는다
dbserver: #db 컨테이너
image: mysql:5.7
volumes: # -v
- db_data:/var/lib/mysql # db_data 볼륨, persistent volume, 컨테이너가 살아져도 데이터가 유지된다.
restart: always # 시스템 종료되어도 다시 시작해줌
environment: # 환경 변수, -e
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
wordpress: # 웹컨테이너
depends_on: # 우선순위, wordpress는 dbserver보다 후순위이다.
- dbserver
image: wordpress:latest #wordpress의 official한 도커 이미지를 다운로드 받는다.
volumes:
- wordpress_data:/var/www/html
ports:
- "80:80"
restart: always
environment:
WORDPRESS_DB_HOST: dbserver:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
docker-compose up -d

yml파일을 백그라운드로 실행시킨다.
192.168.0.189:80 로 접속한다.

이미 변수에 다 wpuser와 wppass가 들어갔기 때문에 사전 설정하지 않아도 된다.




mount된 경로를 알 수 있다.
[root@localhost my_wordpress]# docker-compose port wordpress 80
0.0.0.0:80
몇 번 포트에 연결했는지 볼 수 있다.
Pause
docker-compose pause
docker-compose unpause
pause하면 wp에 접속 안됨.
stop

wordpress 서비스를 완전히 지우고 싶을 때 사용한다.
그러면 state상태가 Exit 0가 되어있다.
rm

compose를 완전히 삭제한다.
down

stop+rm
멈춤과 동시에 삭제한다.
컴포즈들을 삭제해본다.
-v: 볼륨까지 삭제한다.


compose가 삭제되어도 wordpress와 db의 volume은 그대로 남아 있다.

다시 up해본 후, 사이트에 접속해본다.

그러면 아까 달았던 댓글이 남아있는 것을 볼 수 있다.
[root@localhost my_wordpress]# docker-compose down -v
-v 옵션을 이용해서 볼륨까지 삭제해 본다.

다시 volume을 리스트 해 보면 볼륨이 삭제된 것을 볼 수 있다.
도커 컨테이너 모니터링
docker start web-site
docker stats web-site
아까 사용했던 컨테이너를 다시 올린다.

이를 시각화 하는 도구인 'CAdvisor'를 이용해 본다.
VERSION=v0.44.0
[root@localhost my_wordpress]# 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 \
> --privileged \
> --device=/dev/kmsg \
> gcr.io/cadvisor/cadvisor:$VERSION
Unable to find image 'gcr.io/cadvisor/cadvisor:v0.44.0' locally
v0.44.0: Pulling from cadvisor/cadvisor
8572bc8fb8a3: Pull complete
767fa50f0abb: Pull complete
ea01cc345381: Pull complete
292822dcb406: Pull complete
fe825e66ed0f: Pull complete
Digest: sha256:ef1e224267584fc9cb8d189867f178598443c122d9068686f9c3898c735b711f
Status: Downloaded newer image for gcr.io/cadvisor/cadvisor:v0.44.0
dc351e73cd1fde452b4a11c8e1bcb1dccf92a773351cc97d54a1a12f09582377

:8080으로 들어가 본다

.CPU 사용량 등을 알 수 있다.

1개의 Manager Node와 2개의 Workder Node로 시작한다.
세 노드에
cat <<EOF >> /etc/hosts
192.168.0.189 manager1
192.168.1.160 worker1
192.168.1.163 worker2
EOF
입력한다.
그리고 마스터에
[root@manager1 ~]# docker swarm init --advertise-addr 192.168.0.189
Swarm initialized: current node (wefdqvurtejlmyhtxh5ev5m8z) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4a9lntr9mdgydpote22okw3v722onc5ggkptphm79x23jwd5w6-4s3solkns70dodbc3dkft7jxm 192.168.0.189:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
worker1, worker2에 해당하는 명령어를 입력한다.
[root@worker2 ~]# docker swarm join --token SWMTKN-1-4a9lntr9mdgydpote22okw3v722onc5g gkptphm79x23jwd5w6-4s3solkns70dodbc3dkft7jxm 192.168.0.189:2377
This node joined a swarm as a worker.

노드들이 잘 올라왔다.
[root@manager1 ~]# docker service create --name my_web --replicas 3 --publish published=8080,target=80 nginx
s5mkl4yp986oaa6v3b31ir8z7
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
3개의 컨테이너를 nginx를 이용해 동시에 만들고 있다.

- task: swarm의 최소 단위, 쿠버네티스에서는 pod로 불린다.
- service에는 자아 치유의 기능이 있어서 desired state로 유지하려고 한다.

master1, worker1, worker2 세 군데 다 8080포트로 같은 페이지에 들어가진다.
로드밸런싱이 될 수 있다.
[root@manager1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
14e3ffc453c4 nginx:latest "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 80/tcp my_web.2.bespe2ggygblx93l4nkcf7jo8
[root@manager1 ~]# docker exec 14e3ffc453c4 sh -c "echo "manager1" >> /usr/share/nginx/html/index.html"
같은 작업을 manager1, worker1, 2에 반복한다.


접속할 때마다 바뀐다.(라운드로빈 방식은 아님)

worker 노드에서 보려고 하면 권한 문제로 실행되지 않는다.
dockerswarm의 worker node의 ip로도 접속이 가능하고 로드밸런싱이 가능하다.
도커 스케줄링
[root@manager1 ~]# docker service scale my_web=5
my_web scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged
기존 3개에 +2개 해서 총 5개의 노드가 되도록 한다

롤링 업데이트
서비스를 멈추지 않고 퍼센트 단위로 일부분씩 업데이트 하는 것
- 과거 -> 현재 홈페이지로 바뀔 떄 서비스가 멈추지 않는다.
[root@manager1 ~]# docker service update --image hyun141/web-site:v1.0 my_web
my_web
overall progress: 6 out of 6 tasks
1/6: running [==================================================>]
2/6: running [==================================================>]
3/6: running [==================================================>]
4/6: running [==================================================>]
5/6: running [==================================================>]
6/6: running [==================================================>]
verify: Service converged
페이지 업데이트가 서서히 일어난다.
롤백
[root@manager1 ~]# docker service rollback my_web
my_web
rollback: manually requested rollback
overall progress: rolling back update: 6 out of 6 tasks
1/6: running [> ]
2/6: running [> ]
3/6: running [> ]
4/6: running [> ]
5/6: running [> ]
6/6: running [> ]
verify: Service converged
바로 이전 버전으로 되돌아 간다. 그 이상의 버전으로 내려갈 순 없다.

[root@manager1 ~]# docker service ps my_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
8amazii0t5f2 my_web.1 nginx:latest worker1 Running Running 2 minutes ago
t2guneg3z58e \_ my_web.1 hyun141/web-site:v1.0 worker1 Shutdown Shutdown 2 minutes ago
zw3c7isij0wo \_ my_web.1 nginx:latest worker1 Shutdown Shutdown 8 minutes ago
vddxx2y11rlj my_web.2 nginx:latest manager1 Running Running 2 minutes ago
peesr4jhepks \_ my_web.2 hyun141/web-site:v1.0 manager1 Shutdown Shutdown 2 minutes ago
bespe2ggygbl \_ my_web.2 nginx:latest manager1 Shutdown Shutdown 8 minutes ago
8upym1kcy9jt my_web.3 nginx:latest worker2 Running Running 2 minutes ago
5jygxpsl5ide \_ my_web.3 hyun141/web-site:v1.0 worker2 Shutdown Shutdown 2 minutes ago
xmzblsoc2w0j \_ my_web.3 nginx:latest worker2 Shutdown Shutdown 8 minutes ago
6mq732gu37qr my_web.4 nginx:latest manager1 Running Running 2 minutes ago
csboo6bxh2ru \_ my_web.4 hyun141/web-site:v1.0 manager1 Shutdown Shutdown 2 minutes ago
f0wf8o4peaap \_ my_web.4 nginx:latest manager1 Shutdown Shutdown 10 minutes ago
o9ulad42x47t my_web.5 nginx:latest worker2 Running Running 2 minutes ago
igt8o2lc7wga \_ my_web.5 hyun141/web-site:v1.0 worker2 Shutdown Shutdown 2 minutes ago
s11kyufez63g \_ my_web.5 nginx:latest worker2 Shutdown Shutdown 9 minutes ago
jn9mkpx828b3 my_web.6 nginx:latest worker1 Running Running 2 minutes ago
sin1p6e2yjdq \_ my_web.6 hyun141/web-site:v1.0 worker1 Shutdown Shutdown 2 minutes ago
7mvdvf2k143i \_ my_web.6 nginx:latest worker1 Shutdown Shutdown 8 minutes ago
[root@manager1 ~]# docker service rm my_web
my_web
[root@manager1 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
삭제할 때는 똑같이 rm 쓰면 된다.
클러스터에서 특정 노드 드레인하기
worker1을 수정하기 위해, ,, ,
master1을 손보기 위해? worker1과 worker2를어떻게 손쓰기?
[root@manager1 ~]# docker service create --name my_web --replicas 3 --publish published=8080,target=80 hyun141/web-site:v1.0
cat0g0f5awyjnwdga3u4ez52t
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
[root@manager1 ~]# docker service ps my_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
q5xje9s08gl6 my_web.1 hyun141/web-site:v1.0 manager1 Running Running 56 seconds ago
bgk909cpkk5a my_web.2 hyun141/web-site:v1.0 worker2 Running Running 57 seconds ago
hfep53xku01f my_web.3 hyun141/web-site:v1.0 worker1 Running Running 57 seconds ago
[root@manager1 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
wefdqvurtejlmyhtxh5ev5m8z * manager1 Ready Active Leader 20.10.17
nu2f9auyyvm2tvhtziz4ckwgm worker1 Ready Active 20.10.17
uiq5r00oq9p4cyoxjiwzbn15u worker2 Ready Active 20.10.17
[root@manager1 ~]# docker node update --availability drain worker1
worker1
[root@manager1 ~]# docker service ps my_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
q5xje9s08gl6 my_web.1 hyun141/web-site:v1.0 manager1 Running Running 2 minutes ago
bgk909cpkk5a my_web.2 hyun141/web-site:v1.0 worker2 Running Running 2 minutes ago
075vkphz0xsb my_web.3 hyun141/web-site:v1.0 manager1 Running Running 16 seconds ago
hfep53xku01f \_ my_web.3 hyun141/web-site:v1.0 worker1 Shutdown Shutdown 17 seconds ago

manager가 걸려있는게 실제 manager가 아니고 복제된 것이다.
[root@manager1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90229890c26b hyun141/web-site:v1.0 "nginx -g 'daemon of…" 4 minutes ago Up 3 minutes 80/tcp my_web.3.075vkphz0xsbv99vn4k57lavy
b04040196819 hyun141/web-site:v1.0 "nginx -g 'daemon of…" 6 minutes ago Up 6 minutes 80/tcp my_web.1.q5xje9s08gl6ye4mwum8upfet
[root@manager1 ~]# docker rm -f 90229890c26b
90229890c26b
삭제해보면,

다시 생성되어 있다.
컨테이너를 마음대로 지울 수 없다.
desired capacity 3을 맞추기 위해

worker1을 보면 Drain 되어 있다.

다시 worker1을 활성화 시킨다.

manager1로 갔던 worker1이 다시 돌아와 있지는 않다 그대로 master1에 있다
[root@manager1 ~]# docker service scale my_web=2
my_web scaled to 2
overall progress: 2 out of 2 tasks
1/2:
2/2: running [==================================================>]
verify: Service converged
[root@manager1 ~]# docker service scale my_web=3
my_web scaled to 3
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
[root@manager1 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
wefdqvurtejlmyhtxh5ev5m8z * manager1 Ready Active Leader 20.10.17
nu2f9auyyvm2tvhtziz4ckwgm worker1 Ready Active 20.10.17
uiq5r00oq9p4cyoxjiwzbn15u worker2 Ready Active 20.10.17
[root@manager1 ~]# docker service ps my_web
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
q5xje9s08gl6 my_web.1 hyun141/web-site:v1.0 manager1 Running Running 17 minutes ago
bgk909cpkk5a my_web.2 hyun141/web-site:v1.0 worker2 Running Running 17 minutes ago
96qgcoov1bp2 my_web.3 hyun141/web-site:v1.0 worker1 Running Running about a minute ago
만약 worker1으로 다시 돌아오게 하려면, scalein 한 후 다시 scale out 한다.


docker pause를 하면 그 노드에만 더 할당되지 않는다