진행
XE+DB -> private-registry -> docker container run .. -> Iac 첫번째(docker compose.yml)
- docker container attach - 컨테이너로 직접 들어간다(it 옵션을 주고 생성된 컨테이너)
- docker container exec - 컨테이너로 직접 들어가지 않고 외부에서 컨테이너로 명령을 전달하고 결과값을 밖에서 전달받는다.
- docker container run(docker run) - 컨테이너 생성 + 실행
docker run 만 써도 무방하다. container 를 쓰는 이유는 단순 명시하기 위해 쓴다.실행하게 되면 1) 이미지를 로컬 저장소에서 찾는다. 없다면 기본적으로 도커 허브로 접속하여 검색한다. 2) pull 된 이미지를 이용하여 컨테이너 생성하고 실행시킨다. 실행시 문제가 있다면 exit 상태가 된다.
- docker container start - 중지된 컨테이너를 실행
- -it - 대화식 단말 디바이스를 할당하여 Host 가 생성된 컨테이너와 직접 통신이 된다.일반적으로 함께 사용한다.
명령어 마지막에 컨테이너에게 전달할 명령을 써준다. 주로, /bin/bash 또는 /bin/sh를 주로 사용하여 컨테이너 실행시 shell 을 동작시키게 한다
- -d - 컨테이너를 백그라운드에서 실행시킨다.
- --name - 관리를 위한 목적으로 사용한다. 컨테이너 생성되면 각 컨테이너 별로 id,name이 할당 된다. 하지만 별도로 관리의 편의를 위해 이름을 직접 지정할 수 있다.
다수의 컨테이너를 관리할 때에는 별도의 이름을 입력하는 것이 불필요한 작업이 될 것이다. 이때는 작성하지 않는다
- --restart - 처음 생성시, 호스트 재부팅시 컨테이너를 어떻게 실행할 것인가? 웹 서버나 DB와 같이 상시적으로 동작해야하는 컨테이너의 경우에는 초기 생성시 --restart=always로 하여 실행에 문제가 있어도 계속해서 실행을 시도하도록 설정해주는 것이 좋다.
- --env(-e) - 시스템 환경 변수를 컨테이너에 작성한다.
-e PYTHON=/usr/lib/python2 -e PY3=/usr/lib/python3.4
- -v (--volume) - 볼륨 지정
docker container run -d --name db1 -v testvolume1:/var/lib/mysql mysql:5.7 - testvolume1의 볼륨을 iscsi 로 연결. 컨테이너에서는 이 볼륨을 /dev/sda5 와 같은 자신의 디스크로 인식한다 docker container run -d --name db1 -v /testvolume1:/var/lib/mysql mysql:5.7 - /testvolume1이라는 디렉터리를 nfs 로 연결
- -p 호스트의 포트와 매핑하기
보통 동일한 웹 서버 컨테이너 다수를 서비스할 때, 하나의 서버에 다수의 웹 서버 컨테이너를 놓을려면 서버의 각 Port 에 컨테이너 하나씩 지정 해야 하는데, 이는 웹 서비스를 할 때 웹에 접속할 시 Port 를 작성해 접속해야 하므로, 접속에 불편함이있어 이러한 방식은 사용해서는 안된다. 그렇기 때문에 하나의 서버에 하나의 웹 서버 컨테이너를 놓고 서비스를 해야 하며 Cluster로 관리해야 한다. 이때, 다수의 컨테이너들을 Docker Swarm 과 같은 도구로 관리할 수 있다. 이러한 서버들의 앞에 로드 밸런서를 두고 트래픽을 관리하게 한다.
- --link -
rapa@rapa:~$ docker container run -d --name wpdb1 -e MYSQL_ROOT_PASSWORD=test123 -e MYSQL_DATABASE=wordpress -v wpdb1:/var/lib/mysql mysql:5.7
rapa@rapa:~$ docker container run -d --name wp1 -e WORDPRESS_DB_PASSWORD=test123 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_NAME=wordpress -p 8801:80 --link wpdb1:db1 wordpress
rapa@rapa:~$ docker container exec wp1 cat /etc/hosts : : 172.17.0.2 db1 b4ebaf1a6d3a wpdb1 -> link된 컨테이너의 ID,이름,alias명을 IP주소와 함께 등록 172.17.0.3 f9dd0eba6bf7 -> 자신의 ID와 IP주소를 등록
- 컨테이너(linux의 cgroup, namespace)는 이미지를 통해 배포된다.
- 이미지를 생성하는 대표적인 방법은 commit을 이용하는 방법이 있다.
1. commit은 동작중인 컨테이너 이미지화 2. dockerfile을 이용해 build하게 되면 new image를 생성된다. 이 컨테이너를 배포하는 방식이 가장 안정적이다. - build할 때에는 기본적으로 Dockerfile을 인식하게 되는데 만약 다른 이름을 사용한다면 docker build -t myimg:1.0 . docker build -t myimg:1.0 -f dockerfile1 - 일반적으로 두 개 이상의 이미지를 생성하고자 한다면 별도의 디렉토리를 만들고 각 디렉토리에서 별도의 Dockerfile을 생성하는 형식으로 이미지를 만들게 된다.
FROM
- Dockerfile의 제일 상단에는 무조건 FROM을 위치 시켜야한다.
-> base image를 지정하는 것
MAINTAINER
- MAINTAINER는 작성자 정보를 간략히 입력해 둔다. 최근에는 잘 사용하지 않고 대신 LABEL을 사용한다.
예) LABEL auther=yangseunghyun LABEL email=yang@naver.com LABEL version=1.0 LABEL desc=""
RUN
- RUN은 컨테이너가 아닌 base image 자체에 전달하는 명령어
예) FROM centos:7 RUN yum -y install vim # -> base image centos:7에게 vim을 설치한다.
- 여러번 사용 가능하다. 가장 많이 사용하는 명령어
CMD
- CMD는 컨테이너가 배포될 때 실행할 명령어
- 가령 web서버 컨테이너를 실행시키고 싶다면 RUN으로 base image에 web서버를 설치하고 컨테이너가 실해될 때 웹서버 데몬이 동작해야 하므로 CMD를 이용하여 데몬 실행 명령을 전달한다.
ENTRYPOINT
- ENTRYPOINT 역시 컨테이너가 배포될 때 실행할 명령어
CMD vs ENTRYPOINT
base image ENTRYPOINT top CMD -d 10
- 위의 구성을 통해 컨테이너가 배포된다면 각 컨테이너는 컨테이너의 cpu 정보를 10초마다 한번씩 갱신하여 보여준다.
docker container run -d ... -d 2
- CMD는 이미지 내에 있는 정보와 docker container run에서 작성한 정보가 동일한 옵션인 경우 이미지내에 있는 옵션은 무시된다.
- 만약 컨테이너로 실행될때 컨테이너가 동작 시켜야 할 데몬이 많고 해야할 일이 많다면?
ADD a.sh /root/a.sh CMD ./a.sh or CMD ["/bin/bash","/root/a.sh"]
COPY
- COPY는 호스트에 있는 파일 또는 디렉토리를 이미지에 붙여넣기 한다.
- ADD는 COPY의 모든 기능을 포함하고 추가적으로 URL을 통해 파일을 붙여넣기하는것 가능하다
ADD http://www.yang.com/main.jsp /var/www/html/index.jsp 또한 ADD yang.tar.gz /var/www/html
ENV
- ENV는 시스템 환경변수 선언
EXPOSE
- EXPOSE 포트 오픈. 마친 방화벽으로 포트를 여는 것과 같은 효과
EXPOSE 80 8080
VOLUME
- VOLUME은 docker container run -v 와 동일
VOLUME /var/log -> 컨테이너 /var/log를 호스트에 있는 볼륨과 연결해 준다.
- 만약 볼륨 이름을 지정하다면 어떻게 될까
VOLUME testvol1:/var/log ctn1이 testvol1과 연결 ctn2도 testvol1과 연결 된다.
- 만약 컨테이너의 여러 디렉토리를 볼륨과 연결하고 싶다면 어떻게 해야 할까
VOLUME /var/log /var/www/html /var/lib/mysql
WORKDIR
- WORKDIR 작업경로 지정
WORKDIR /var/www | | ----> 사이의 작업은 /var/www에서 이루어진다. | WORKDIR /var/www/html | | -----> 이 부분은 /var/www/html에서 작업이 이루어진다. RUN cd /var/www(X) RUN cd /var/www/html(X)
yaml
- yaml 또는 yml은 들여쓰기가 중요하다
key: value
- value가 한개일 경우에는 바로 옆에 띄어쓰기 후 작성한다.
- value가 여러개인 경우 다음과 같이 사용한다
key: - value1 - value2 -> 리스트 형태로 작성 가능하다.
실습1
Quiz.
- IP 변경 (VMnet10(NAT))
rapa@rapa:/etc/netplan$ sodo vi /etc/netplan/01-network-manager-all.yaml
rapa@rapa:/etc/netplan$ sudo netplan apply
- 위의 파일을 이용하여 xe:1.0 이미지를 만드세요
- 그리고 mysql:5.7을 이용하여 root 패스워드를 test123으로 설정하고, 기본 DB 이름도 지정하되 이름을 xe로 하여 컨테이너를 배포하세요. 컨테이너 이름은 db1으로 하세요
- xe:1.0 이미지를 이용하여 xe1 컨테이너를 생성하되, "2"에서 만든 db1과 link 시키고 외부에서 8888번 포트 를 컨테이너 80번 포트와 매핑시켜서 배포하세요
- 두개의 컨테이너가 정상적으로 배포되었다면 http://211.183.3.112:8888/xe로 접속하면 설치화면으로 들어가게 됩니다. 필요한 내용을 입력하셔서 정상적인 게시판이 보이도록 해 주세요!
- 만약 이미지 생성이 너~무 오래 걸려서 잘 안된다면 도커허브에 있는 kakaorapa/xe:1.0 이미지를 사용하셔도 됩니다.
[풀이]
- 위의 파일을 이용하여 xe:1.0 이미지를 만드세요
rapa@rapa:~/0819/board$ vim dockerfile FROM centos:7 RUN yum clean all RUN yum update -y RUN yum -y install wget git httpd RUN wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm RUN yum -y localinstall remi-release-7.rpm RUN yum -y install epel-release yum-utils RUN yum-config-manager --enable remi-php74 RUN yum -y install php php-fpm php-gd php-mysql php-xml RUN git clone https://github.com/xpressengine/xe-core.git /var/www/html/xe WORKDIR /var/www/html/xe RUN mkdir files RUN chmod 707 -R files WORKDIR /var/www/html RUN chmod -R 707 xe RUN chown -R apache:apache xe EXPOSE 80 CMD httpd -D FOREGROUND
rapa@rapa:~/0819/board$ docker build -t xe:1.0 .
- 그리고 mysql:5.7을 이용하여 root 패스워드를 test123으로 설정하고, 기본 DB 이름도 지정하되 이름을 xe로 하여 컨테이너를 배포하세요. 컨테이너 이름은 db1으로 하세요
rapa@rapa:~/0819/board$ docker container run -d --name db1 -e MYSQL_ROOT_PASSWORD=test123 -e MYSQL_DATABASE=xe mysql:5.7
- xe:1.0 이미지를 이용하여 xe1 컨테이너를 생성하되, "2"에서 만든 db1과 link 시키고 외부에서 8888번 포트 를 컨테이너 80번 포트와 매핑시켜서 배포하세요
rapa@rapa:~/0819/board$ docker container run -d -p 8888:80 --name xe1 --link db1:mysql xe:1.0
- 두개의 컨테이너가 정상적으로 배포되었다면 http://211.183.3.112:8888/xe로 접속하면 설치화면으로 들어가게 됩니다. 필요한 내용을 입력하셔서 정상적인 게시판이 보이도록 해 주세요!
http://211.183.3.112:8888/xe
- 실습 이미지를 다운로드
rapa@rapa:~/0819/board$ docker pull registry rapa@rapa:~/0819/board$ docker pull hyper/docker-registry-web
- 이미지 저장소에 인증 정보를 먼저 보내야한다.
public registry
- docker hub -> 불특정 다수가 접속할 수 있는 공간이고 회원가입을 통해 이미지를 push할 수 있다. pull은 로그인이 없다면 IP 별로 하루에 100개 받을 수 있다.
- 로그인 정보가 있다면 도커 허브에 접속시 config.json에 있는 정보를 먼저 보내서 인증 정보를 확인 받는다.
- 로그인 정보가 있다면 IP가 아닌 사용자별로 100개를 받을 수 있다.
private registry
- 특정 사용자/그룹 사용자만 접속할 수 있다.
- 접속시 docker login 주소 를 입력하여야 한다.
docker login https://10.10.10.10
local
- 본인만 사용한다. 컨테이너 생성시 1차적으로 로컬 저장소를 검색한다.
registry 구축하기
https://docs.docker.com/registry/deploying/ 참조 사이트
사설 저장소
- 사설 저장소는 private-registry(이미지)를 이용하여 구축가능하다.
-> 컨테이너로 배포하여 사용 가능 version 1 - python version 2 - go (일반적으로 version 2 사용한다.)
registry 구축 하기
- registry 이미지 배포하여 저장소 구축(혼자 사용하는 저장소)
rapa@rapa:~/0819/board$ docker container run -d -p 5000:5000 --restart=always --name registry -v /home/rapa/registry:/var/lib/registry registry
- 확인
rapa@rapa:~/0819/board$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ba5d274ad9f9 registry "/entrypoint.sh /etc…" 32 seconds ago Up 30 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry
이미지 push 및 조회
- 일반적으로 이미지의 이름은 아래와 같은 형식을 취해야 한다.
1. public -> yang/myweb:1.0 --> user id를 입력 2. private -> reg.test.com:5000/myweb:1.0 192.168.1.112:5000/myweb:1.0 --> IP 처럼 앞에 주소를 입력 3. local -> myweb:1.0 --> 이미지 이름과 태그만 입력
- 이미지 형식 변경
docker tag centos:7 localhost:5000/mycentos:1.0 - private registry 에 올릴 수 있게 이미지의 형식을 변경한다.
- 이미지 push
docker push localhost:5000/mycentos:1.0
registry 조회
rapa@rapa:~/0819/board$ curl -XGET localhost:5000/v2/_catalog {"repositories":["mycentos"]}
웹 GUI 연결
[설정 예]
docker container run -d -p 5000:5000 --restart=always --name registry -v /home/rapa/registry:/var/lib/registry registry
- 생성한 registry 를 웹 GUI 와 연결
docker run -d -p 8080:8080 --name registry-web --link registry:private -e REGISTRY_URL=http://211.183.3.112:5000/v2 -e REGISTRY_NAME=211.183.3.112:5000 --restart=always hyper/docker-registry-web - 위와 같이 위에 생성한 registry 와 link 하여 웹 GUI 컨테이너를 배포
registry 의 Image Pull
- 사설 저장소에서 이미지 pull 하기
docker pull localhost:5000/mycentos:1.0
로컬 저장소에 있는 이미지 삭제
docker image rm localhost:5000/mycentos:1.0
실습2-2
- IP 변경 (VMnet0)
rapa@rapa:/etc/netplan$ sodo vi /etc/netplan/01-network-manager-all.yaml
rapa@rapa:/etc/netplan$ sudo netplan apply
사설 저장소 server
- registry 이미지 배포하여 저장소 구축(혼자 사용하는 저장소)
docker container run -d -p 5000:5000 --restart=always --name registry -v /home/rapa/registry:/var/lib/registry registry
- 이미지 형식 변경
docker tag centos:7 192.168.1.112:5000/myweb:yang
- 이미지 push
docker push 192.168.1.112:5000/myweb:yang
- 생성한 registry 를 웹 GUI 와 연결
docker run -d -p 8080:8080 --name registry-web --link registry:private -e REGISTRY_URL=http://192.168.1.112:5000/v2 -e REGISTRY_NAME=192.168.1.112:5000 --restart=always hyper/docker-registry-web
client
- 인증정보 필요 없이 접속할 수 있도록 설정, 보안상 좋지 않다. (서버 IP)
rapa@rapa:~/0819/board$ sudo vi /etc/init.d/docker DOCKER_OPTS=--insecure-registry 192.168.1.112:5000
- 파일 설정 (client IP)
rapa@rapa:~/0819/board$ sudo vi /etc/docker/daemon.json { "insecure-registries": ["192.168.1.112:5000","192.168.1.121:5000","192.168.1.123:5000"] }
- 도커 데몬 재시작
rapa@rapa:~/0819/board$ sudo service docker restart
- 파일 설정 확인
rapa@rapa:~/0819/board$ docker info Insecure Registries: 192.168.1.112:5000 192.168.1.121:5000 192.168.1.123:5000 127.0.0.0/8
- 이미지 형식 변경
rapa@rapa:~/0819/board$ docker image tag centos:1.0 192.168.1.121:5000/babo:1.0
- 이미지 push
rapa@rapa:~/0819/board$ docker push 192.168.1.121:5000/babo:1.0
- [확인]
- 현재는 registry에는 inbound 에 대해 방화벽이나 보안이 없다.
- 사설 저장소로는 registry, harbor 를 사용할 수 있다
- rapa@rapa:~/0818/board$ docker container rm -f $(docker container ls --all -aq)
컨테이너 리스트 확인
- docker container ls --all
- 일반적으로 웹서비스는 3tier 구조를 갖는다.
web server - was server - DB 각 서버들은 다수로 두고, Auto Scale 이 가능하게 한다 이 구조는 Db, WAS, WEB 을 순서대로 만든다. WAS 는 Db 와 link 를 걸고, WEB 는 WAS 와 link 를 건다
- 위와 같은 구조를 docker container run을 이용하여 구성하게 되면
1. 복잡하다. 2. 동일 구조를 다시 만드는데 오랜 시간이 걸린다. 3. 변경이 용이하지 않다.
docker-compose & docker stack
- 위와 같은 구조를 하나의 명세서에 작성하는 방법을 도커에서 제공하는 이를 docker-compose라 부른다.
- docker-compose는 docker에서 제공하는 기본 서비스가 아니므로 별도로 추가 설치가 필요하다.
- 단 docker-compose는 클러스터 환경에서의 사용이 아니라 1대의 도커 서버에서 동작한다.
- 실제 클러스터 환경에서는 docker-compose + 클러스터 환경(docker swarm) = "docker stack"
- 명세 파일에 아래의 오브젝트를 구성하게 된다.
sevice -> 컨테이너 volume network
docker network driver
bridge
- KVM의 NAT 스위치와 같은 역할을 수행한다.
- 독립적인 사설 주소 대역을 갖는다.
-> 기본적으로 도커는 bridge type의 docker0를 생성하여 모든 컨테이너를 연결한다.
host
- 호스트 PC의 IP주소를 그대로 사용한다.
none
- 네트워크에 연결되지 않음
- 가상의 네트워크 private1 생성(자동으로 네트워크 대역 설정됨)
rapa@rapa:~/0819/board$ docker network create private1
- 생성된 가상 네트워크 확인
rapa@rapa:~/0819/board$ docker network ls NETWORK ID NAME DRIVER SCOPE b2d9588e10e2 bridge bridge local 3ead376f089f host host local 39430d1f4412 none null local 401beb8aaa84 private1 bridge local
- 임의의 네트워크 주소 대역 확인
rapa@rapa:~/0819/board$ docker network inspect private1
- 컨테이너 배포
rapa@rapa:~/0819/board$ docker container run -d --net=private1 centos:7
- 컨테이너 목록
rapa@rapa:~/0819/board$ docker container ls -a
- IP 확인해보기
rapa@rapa:~/0819/board$ docker inspect ip [컨테이너 이름]
- 우리가 원하는 대역의 주소를 지정하여 네트워크 생성하기
rapa@rapa:~/0819/board$ docker network create --driver bridge --subnet 10.10.0.0/16 --ip-range 10.10.10.0/24 --gateway 10.10.10.1 private2
- 배포 후 접속
rapa@rapa:~/0819/board$ docker container run -it --name centos11 --net=private2 --ip=10.10.10.10 centos:7 /bin/bash [root@3113ae5a413d /]#
- 상세 정보 확인
rapa@rapa:~/0819/board$ docker container inspect centos11
- 실습중 docker-compose 설치가 필요합니다. 아래 내용 복사해서 설치할 수 있다.
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version
alias 추가
- 'docker-compose' alias 추가
vi ~/.bashrc alias dc='docker-compose'
- ~/.bashrc 저장
source ~/.bashrc
docker compose
- docker container run 명령들을 YAML 파일에 작성하는 것
- 다음의 사항을 정의한다.
version : 버전별로 지원되는 옵션이 달라진다. 지원이 되지 않는등의 문제가 있다면 해당 버전을 홈페이지에서 반드시 확인해야 한다. service : 실제로 서비스를 제공하는 컨테이너에 대한 정의 volume : 컨테이너에 연결할 볼륨을 정의한다. (필수 아님) network : 컨테이너들을 연결할 네트워크를 정의한다(필수아님-> 작성하지않으면 모든 컨테이너는 docker0 에 연결된다)
- 각 항목의 하위 항목을 정의하려면 들여쓰기 "매우 " 중요하다.
- 일반적으로 YAML 파일은 tab을 인식하지 않으므로 반드시 space bar를 이용해야 한다.
- 버전 정의 방법
version: '3.9'
- 서비스 정의 방법
service: myctl1: image: centos:7 environment: MYSQL_ROOT_PASSWORD: test123 MYSQL_DATABASE: wordpress networks: - private1 - private2 myctl2: build: . environment: - WORDPRESS_DB_USER=root - WORDPRESS_DB_NAME=wordpress depends_on: # 실행 순서 결정. myctl1 이 먼저 실행됨. mysql1으 ㅣ 동작완료를 확인하지는 않는다. - myctn1 ports: - "8080:80" # 시간을 의미하는 12:30과 구분하기 위해 일반적으로 ""을 붙인다. - "33061:3306" # -p 33061:3306 - "8080" # -P 8080 호스트의 랜덤포트와 컨테이너의 8080을 연결 - "8081-8085" # 랜덤 포트 networks: - private2
- 네트워크 정의 방법
networks: private1: driver: bridge --> private1은 브릿지 타입으로 생성된다. external: true --> 기존에 만들어 두었던 private1을 재활용한다.
간단한 실습
rapa@rapa:~/0819/board$ touch docker-compose.yml
- docker-compose.yml 작성
rapa@rapa:~/0819/board$ vim docker-compose.yml version: "3.0" services: wordpress: image: wordpress ports: - "8888:80" environment: - WORDPRESS_DB_PASSWORD=test123 - WORDPRESS_DB_NAME=wpdb - WORDPRESS_DB_USER=root depends_on: - db links: - db:mysql db: image: mysql:5.7 environment: - MYSQL_ROOT_PASSWORD=test123 - MYSQL_DATABASE=wpdb
- 실행
docker-compose up -d
- 실행시 만약 아래와 같은 오류가 난다면 다음 명령어를 해준다.
bash: /usr/local/bin/docker-compose: Permission denied
rapa@rapa:~/0819/board$ sudo chmod -R 777 /usr/local/bin
- http://192.168.1.112:8888 접속 후 wordpress 확인