[2023-05-26 금] 도커 최종, 도커 컴포즈, 도커 모니터링, 도커스웜
- 목차 -
1. gcp에서 워드프레스 dbserver 만들기
어제 실수했던 도커허브 리포지토리에 있는 이미지 지우기
GCP 인스턴스 웹콘솔에서 SSH 접속
컨테이너 안에 있는 스토리지를 이미지로 만들고싶었다(근데 안됨)
원래는 스토리지를 빼놓고 이미지로 만들어야함
$ sudo su -
# timedatectl set-timezeon Asia/Seoul # 인스턴스 타임존 맞추기
mkdir dbserver && $_
도커 이미지 과정 추상화
gcp-dbserver 도커 컨테이너 만들기
# 상태저장이 되도록 함
# docker run -itd -p 3306:3306 --name mysql --network gcp-network ubuntu:18.04 # 우분투를 base image로 gcp-network에 mysql 컨테이너 생성+실행. -itd를 넣어서 컨테이너가 up된 상태로 계속 실행되도록 명령
// # docker rmi -f $(docker images -q) # 이미지를 전부 지우는 명령
# docker ps # mysql 컨테이너 프로세스가 띄워졌다
COMMAND가 떠있다. 떠있어야 컨테이너가 UP이 된다. 우분투 이미지 자체 안에 커맨드가 안들어가있다. -it 명령을 통해 컨테이너 안쪽에 들어갈 수도 있고 커맨드/bin/bash 기능을 수행시켜주는 역할을 할 수 있다
# docker exec -it mysql bash # mysql 컨테이너 안으로 들어감
# cat /etc/os-release # debian이나 우분투 os의 상세 정보를 볼 수 있다.
# sed -i 's/archive.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/sources.list # s/ 찾을 사이트 /ftp 변경 사이트. 경로에 있는 파일명을 바꿀 것이다. 빠르게 설치하기 위함
# apt-get update # 저장소가 바뀐걸 업데이트
# apt-get install -y mariadb-server
# sed -i "s/bind-address/#bind-address/g" /etc/mysql/mariadb.conf.d/50-server.cnf # bind-adress는 로컬에서만 접속하도록 하는 것. 접근제어 하는 것을 사용하지 않도록 #을 붙여주는 치환 명령. 뒤에 경로는bind-address가 위치한 파일
# service mysql start # mysql 데몬을 실행시키는 명령. service는 systemctl 이전 버전
# mysql_secure_installation # enter(현재 패스워드없음) > Y(root 패스워드 설정) > y > y > y > y
# service mysql restart
# mysql -u root -p # 방금 만든 루트 패스워드로 mysql 접속
# CREATE USER 'wpuser'@'%' IDENTIFIED BY 'wppass';
CREATE DATABASE IF NOT EXISTS wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'%';
quit
2. 워드프레스 도커 dbserver 갈아끼우기
# docker run -d -p 80:80 --name my-wp --network gcp-network apeachcloud/my-wp:v1.0 # 도커허브에 있는 이미지를 가지고 컨테이너 생성+실행
# docker ps
# docker rename mysql dbserver # 컨테이너 이름 변경
# curl ipconfig.io # 인스턴스 ip를 Route53에 레코드 등록
어제의 오류의 발생 원인 : 커밋할 때 컨테이너를 stop(중지)하고 커밋+push를 진행해야했다
blog.changhoon.shop으로 접속하면 my-wp 컨테이너에 있는 워드프레스가 뜬다
댓글남기기
# docker stop dbserver my-wp # commit과 push하기 위해 반드시 컨테이너를 중지해야한다
# docker commit -a "peach" -m "wordpress" my-wp apeachcloud/gcp-wordpress:tiger
# docker push apeachcloud/gcp-wordpress:tiger
# docker commit dbserver mysql-base:v1.0 # 임시 커밋으로 mysql-base:v1.0으로 이미지를 만든다. -a 명령과 -p는 필수가 아니다.
# docker iamges # mysql-base:v1.0 이미지가 만들어졌다. 도커 컨테이너로 되려면 도커 커맨드를 사용하게 하려면 엔트리포인트나 CMD를 넣어줘야한다
# vi Dockerfile # 내가 만든 이미지에 커맨드를 하나 추가해서 다시 이미지를 만든다. 이렇게 상태저장을 할 수 있다. 정식 방법이 아닌 편법. 정식 방법은 데이터를 빼냈다가 다시 붙이는 방식으로 가야하는데 지금은 상태저장상태로 push하기 위해서 mysqld를 넣어줌. 이 작업을 안하면 docker run이 되지 않는다
FROM mysql-base:v1.0
ENTRYPOINT ["mysqld"] # 데몬 실행 명령어 mysqld
# docker build -t apeachcloud/gcp-dbserver:eagle . # 현재 경로의 Dockerfile을 기반으로 이미지 생성
# docker push apeachcloud/gcp-dbserver:eagle
# docker ps -a
# docker rm -f ce0fdf5259a1 a852188d9bfe # 현재 생성되어있는 컨테이너(본뜬 컨테이너) 지우기
# docker run -d -p 3306:3306 --name dbserver --network gcp-network apeachcloud/gcp-dbserver:eagle
# docker run -d -p 80:80 --name wordpress --network gcp-network apeachcloud/gcp-wordpress:tiger
접속테스트
댓글이 잘 있는 것을 확인하였고 댓글을 하나 남긴다
# docker stop dbserver
# docker commit -a "peach" -m "gcp-wp-2" dbserver apeachcloud/gcp-dbserver:falcon
# docker rm -f dbserver # dbserver를 지우면 접속이 끊긴다
# docker run -d -p 3306:3306 --name dbserver --network gcp-network apeachcloud/gcp-dbserver:falcon
# docker ps
다시 접속하면 페이지가 정상적으로 뜨고 댓글이 남겨져있는 것으로 상태저장이 된 것을 확인할 수 있다
# docker images
3. 개발자 도커 활용
onbuild 명령어 활용
--- 운영자 역할 운영자가 이미지를 처음으로 이미지를 빌드한다. 그 뒤 개발자가 이미지를 빌드할 떄 ADD 명령이 수행된다. 개발자는 운영자에게 받은 도커파일과 tar파일을 같은 경로로 놓아두고 빌드하고 도커허브로 commit+push하면 되는 것.
# mkdir onbuild && cd $_
# 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/ # ADD는 tar파일을 풀 수 있는 기능이 있다. 운영자가 빌드하면 남게되는 명령
CMD ["nginx", "-g", "daemon off;"] # 도커파일을 이미지로 실행을 시키면 nginx가 올라가서 웹 이미지를 갖춘다
docker서버가 운영자 tester 서버가 개발자 역할을 할 것. 개발자를 위한 web-base:v1.0을 도커허브에 올리고 Dockerfile을 만들어서 개발자에게 보내준다
# ls
# cd onbuild # Dockerfile은 개발자한테 줄 것. Dockerfile.base는 운영자가 처음 빌드할 도커파일
운영자는 개발자에게 onbuild파일을 만들고 소스코드를 tar로 만들어주세요
$ mkdir onbuild && cd $_
aws.tar파일이 개발자가 만든 것이라 가정
$ sudo cp ~/aws.tar .
$ mv aws.tar website.tar # 개발자에게 tar 이름을 website로 시작해달라고한다. ADD 명령을 설계할 때 운영자가 지정하기 때문
# scp Dockerfile peach@192.168.1.202:/home/peach/onbuild # 운영자는 개발자에게 초기 빌드를 마친 Dockerfile을 보낸다
$ docker build -t apeachcloud/web-site:aws . # Dockerfile은 같은 경로에 있는 website.tar파일을 물귀신처럼 같이 빌드된다.
$ docker images # 이미지가 생성되었다
$ docker run -d -p 80:80 --name=web-site apeachcloud/web-site:aws # 생성한 이미지를 가지고 컨테이너를 만들어주세요
접속테스트
# docker login
# docker push apeachcloud/web-site:aws # 빌드하고 접속테스트에 성공한 이미지를 push
웹사이트가 리뉴얼되었다. 새로운 tar파일을 개발자 환경에서 업로드한다
$ mv website.tar aws.tar
$ cp ~/food.tar .
$ mv food.tar website.tar
$ docker build -t apeachcloud/web-site:food . # 새롭게 리뉴얼된 tar파일을 도커 이미지를 빌드한다.
$ docker run -d -p 8080:80 --name web-site2 apeachcloud/web-site:food # 생성한 이미지로 컨테이너를 생성+실행
접속테스트
# docker push apeachcloud/web-site:food # 도커 허브에 새롭게 리뉴얼된 사이트의 이미지를 push. '리포지토리/이미지 이름:태그' 순서
도커허브에서 방금 작업했던 이미지를 확인할 수 있다
--- 도커 사설 레지스트리(GCP)
도커 허브는 퍼블릭하게 도커 이미지를 올리고 공유할 수 있는 공간이다.
사설 레지스트리(GCP)는 프라이빗하게 공유할 수 있는 공간. 도커허브가 마비될 수도 있기 때문에 개발자는 여기에도 push해줘야한다
GCP 세션
# docker run -d -p 5000:5000 --restart=always --name private-docker-registry registry # 5000번 포트로 껐다켜져도 서버가 켜지면 컨테이너도 자동으로 실행되도록 private-docker-registry이름. registry라는 도커 이미지가 있다. ':버전'을 적지 않으면 가장 최신의 이미지를 가져온다
사설 리포지토리가 등록하는게 아니라 클라이언트가 세팅해야함
# vi /etc/docker/daemon.json # 클라이언트가 세팅해야하는 값{ "insecure-registries":["blog.changhoon.shop:5000"] } # 이 도메인을 적어야만 저장소를 이용할 수 있다
# systemctl restart docker # restart하면 컨테이너가 다 내려가지만 registry는 always명령을 통해 자동으로 실행된다
# docker update --restart always dbserver # 컨테이너가 실행중이어도 always 명령을 줄 수 있다
# docker update --restart always wordpress
# systemctl restart docker
# docker ps # always 명령이 적용되어서 restart되어도 컨테이너가 UP되었다
4. 사설 레지스트리(GCP)에서 이미지 공유
GCP 방화벽 열기
현재 gcp 인스턴스에 5000번 포트가 열려있지 않다. 방화벽을 열어줘야한다
정책 이름 'default-5000'
트래픽 방향 '수신'
일치 시 작업 '허용'
대상 '네트워크의 모든 인스턴스'
소스 IPv4 범위 '106.253.56.124/32' # 강의실 내 IP
지정된 프로토콜 및 포트 'TCP' - 포트 '5000'
우분투(개발자) 세션
$ vi /etc/docker/daemon.json # 클라이언트가 설정해야한다.
{ "insecure-registries":["blog.changhoon.shop:5000"] }
$ systemctl restart docker
$ docker images # 생성했던 food와 aws 이미지를 사설 레지스트리에 push해야한다
태깅 : 이미지를 별칭(별명)을 달아주는 것. 이미지의 ID는 동일하지만 태깅이 다를 수 있다
$ docker tag apeachcloud/web-site:aws blog.changhoon.shop:5000/web-site:aws
$ docker tag apeachcloud/web-site:food blog.changhoon.shop:5000/web-site:food
$ docker images # 이미지 ID는 같지만 리포지토리가 다른 이미지가 생성되었다
$ docker push blog.changhoon.shop:5000/web-site:aws # 사설 레포지토리로 이미지를 push
$ docker push blog.changhoon.shop:5000/web-site:food
도커 운영자 세션 # 도커 운영자도 인증해야한다
# vi /etc/docker/daemon.json # 클라이언트
{ "insecure-registries":["blog.changhoon.shop:5000"] }
# systemctl restart docker
# docker run -d -P --name aws blog.changhoon.shop:5000/web-site:aws # gcp 사설 리포지토리에 올려놓은 aws 이미지를 이용해서 운영자 서버에서 컨테이너를 띄움
# docker run -d -P --name food blog.changhoon.shop:5000/web-site:food # food 이미지를 이용해서 컨테이너를 띄움
접속테스트
# docker ps
컨테이너 정리하기
# docker container prune # 중지되어있는 컨테이너 모두 지우기
# docker rm -f 0abad8184638 cfb62a752597 # 실행되어있는 컨테이너 지우기
# docker rmi -f $(docker images -q) # 이미지 아이디를 찾아서 모두 지움
5. 도커 컴포즈 명령어
# 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: # 생성할 컨테이너 이름
image: mysql:5.7 # 컨테이너 이미지
volumes: # 컨테이너 마운트 경로. persistent 볼륨을 통해 백업해야한다. 원래 이렇게 해야한다. 앞에선 편법을 써서 통째로 이미지로 구워버렸음
- db_data:/var/lib/mysql # db_data는 볼륨 이름이다. 도커 컴포즈가 볼륨을 생성할 수 있다 Mountpoint 경로가 너무 길기 때문에 볼륨 이름으로 관리한다. /var/lib/mysql은 db컨테이너 데이터가 들어있는 곳.
restart: always # 껐다 켜져도 컨테이너가 UP하는 기능
environment: # -e # key:value형식으로 환경을 꾸밈
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
wordpress: # 생성할 컨테이너 이름
depends_on: # 우선순위가 앞서야할 것을 적어준다. wordpress 컨테이너 실행에 앞서서 dbserver 컨테이너를 실행
- dbserver
image: wordpress:latest # wordpress 컨테이너 이미지
volumes: # 도커 Host에 저장할 데이터. 컨테이너가 지워져도 복원이 쉽다
- wordpress_data:/var/www/html
ports: # -p 80:80 # 포트번호를 지정하지 않으면 기본 포트로 지정된다.
- "8888:80" # Host의 포트번호를 8888로 지정한다
restart: always # 껐다 켜져도 컨테이너가 실행되도록 설정
environment: # 환경 변수 key:value로 정의. 앞서 dbserver컨테이너의 값들을 넣어준다
WORDPRESS_DB_HOST: dbserver:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass
WORDPRESS_DB_NAME: wordpress
volumes: # 도커 컴포즈가 볼륨을 생성한다. Mountpoint를 만듦
db_data: {}
wordpress_data: {}
version: "3.3"
services:
dbserver:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment: # -e
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
wordpress:
depends_on:
- dbserver
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports: # -p 80:80
- "8888: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 # 경로에 있는 docker-compose.yml 스크립트를 실행한다. -d 명령은 백그라운드 실행. 도커 컴포즈가 세팅되고 실행된다. 네트워크 세팅이 안되면 컨테이너 이름이 도메인처럼 안된다. 컨테이너 간에 도메인 이름을 사용하게 하기 위해 네트워크를 세팅한다. 폴더의 이름이 접두어로 달려서 이름이 생성된다
# docker-compose ps
접속테스트 # db와 web이 연동 작업이 끝났을 때 나오는 화면
최신 버전의 워드프레스가 잘 설치되었다
# docker-compose pause # 2개의 컨테이너를 한 꺼번에 일시 중지(잠시 멈춤, 재개속도 빠름). stop은 전원을 끄는 것.
# docker-compose unpause
6. 도커 컨테이너 모니터링
# docker-compose port wordpress 80 # 컨테이너의 80포트와 연결된 포트포워드 정보가 나옴
# docker-compose config # docker-compse 스크립트가 나온다
# docker network ls # 생성시 네트워크 설정을 안해도 자동으로 설정되었다
# docker inspect network 09eb4354f9cf
# docker-compose stop wordpress
# docker-compose rm wordpress
# docker-compose down # stop + rm 명령. 컨테이너를 전부 삭제. 자동으로 생성해줬던 네트워크도 삭제된다
# docker-compose down --rmi all # 이미지까지 지우는 명령
# docker-compose down -v # 볼륨을 지우는 명령
도커 컨테이너 모니터링
# 도커 컨테이너를 모니터링하는 컨테이너 생성+실행
VERSION=v0.44.0 # use the latest release version from https://github.com/google/cadvisor/releases
docker run \
--volume=/:/rootfs:ro \ # 마운트할 항목. Host : 컨테이너. 'ro'는 read only
--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 \ # 8080포트로 들어오면 8080포트로 포트포워딩
--detach=true \ # 백그라운드 실행
--name=cadvisor \
--privileged \ # 권한 관련된 보안
--device=/dev/kmsg \ # 커널의 로그 데이터를 얻기 위해서 리눅스의 스트림 다바이스 장치
gcr.io/cadvisor/cadvisor:$VERSION # 이미지 경로. gcr은 google cloud registry
VERSION=v0.44.0 # use the latest release version from https://github.com/google/cadvisor/releases
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
# docker-compose up -d # 앞에서 다 지워버려서 다시 모니터링할 이미지, 볼륨, 컨테이너를 생성
모니터링 접속
Virtual Box 가상머신의 리소스 정보가 나온다
7. 도커스웜 실행
새로고침 연타
새로고침을 마구 하면 CPU 변화량이 요동친다
# docker-compose down # 컨테이너가 stop+rm
# docker system df # 컨테이너 disk크기와 마운트 정보를 가져온다
# docker system prune -a -f # 컨테이너 네트워크을 다 정리해줌.
# free -h # 마스터는 최소 CPU 2core에 메모리 4G여야 한다
도커 스웜(Cluster) 세팅
Docker Host가 마비될 수 있기 때문에 두 대 이상의 클러스터로 구성한다
센토스 도커 설치
# curl -fsSL https://get.docker.com/ | sh
# yum -y install bash-completion wget unzip mysql
# curl https://raw.githubusercontent.com/docker/docker-ce/master/components/cli/contrib/completion/bash/docker -o /etc/bash_completion.d/docker.sh
# systemctl enable --now docker
# poweroff
manager1이 디스크를 많이 차지하고 연결된 복제는 디스크 공간을 많이 차지하지 않는 worker1 생성. manager1이 잘못되면 마비될 수 있다. 지금은 용량을 공유해서 디스크 사용량을 작게함. 실무에선 완전한 복제 사용
똑같이 한 번 더해서 worker2를 만든다
그룹으로 묶고 가상머신 실행
manager1 세션
# hostnamectl set-hostname manager1
# firewall-cmd --permanent --zone=public --add-port=2377/tcp # 서로가 통신하기 위한 2377포트를 열어준다. 매니저만 열어줌
# firewall-cmd --reload
# hostnamectl set-hostname manager1
# hostnamectl set-hostname worker1
# hostnamectl set-hostname worker2
MultiExec 기능
# cat <<EOF > /etc/hosts
192.168.1.166 manager1 # 도커 main Host
192.168.1.232 worker1 # 일꾼들로서 컨테이너들을 담고있다
192.168.1.235 worker2
EOF
# ping manager1 # manager1에서 worker1,2 서버 이름으로 핑이 나간다. host에 추가했기 때문
8. 도커 스웜 복제
-manager1 세션
# docker swarm init --advertise-addr 192.168.1.166 # 토큰 정보가 나온다.
worker1,2 세션에 토큰 정보를 넣어서 연결한다
# docker swarm join --token SWMTKN-1-0cvvrx2jhzd25z6wdrsvr8nvb25iarwdwrplsbgxqtbs6xyhca-3tbwev2eszxsnb0x5ov7kk0tg 192.168.1.166:2377
-manager1 세션
# docker node ls # 클러스터 연결이 되었다
# docker service create --name my_web --replicas 3 --publish published=8080,target=80 apeachcloud/web-site:food
# 도커허브에 저장되어있는 food.tar 이미지로 my_web 컨테이너 총 3개 만든다. published는 docker Host의 포트
최소 단위가 컨테이너가 아니고 task라고 캡슐처럼 컨테이너를 집어넣는다.
task안에 컨테이너가 여러 개 들어갈 수 있다
또 하나의 노드 안에 여러개의 task로 존재할 수 있다. 쿠버네티스에서는 task를 pod라고 부른다
Swarm manager는 task 단위로 관리한다
# docker service ls
접속테스트 # manager1, worker1, worker2 각각의 IP로 접속이 가능하다. 도커스웜 클러스터에 구축된 웹서버는 로드밸런싱이 된다. 라운드로빈 방식이 아니다. least connect 방식
# docker service ps my_web # my_web 서비스 이름으로 상세내역 확인. 컨테이너 이름이 my_web.1, my_web.2, my_web.3으로 각각의 노드에 컨테이너가 생성되었고 실행 중이다
# docker service logs my_web # 현재 쌓인 로그가 없다
# docker service inspect --pretty my_web # pretty는 조금 더 간소화해서 보여주는 명령. Endpoint Mode: vip 옵션이 로드밸런서 방식이다
# docker service scale my_web=6 # 수동으로 컨테이너 크기를 늘리는 명령. 생성되는 컨테이너를 task에 공평하게 분배한다
# docker service ps my_web
# docker service rm my_web # manager에서 제거 명령 실행