도커에 대하여3 (docker, docker-compose) 8.19

양승현·2022년 8월 19일
0

docker

목록 보기
3/12

진행
XE+DB -> private-registry -> docker container run .. -> Iac 첫번째(docker compose.yml)

◎ docker container 명령어

  • docker container attach - 컨테이너로 직접 들어간다(it 옵션을 주고 생성된 컨테이너)
  • docker container exec - 컨테이너로 직접 들어가지 않고 외부에서 컨테이너로 명령을 전달하고 결과값을 밖에서 전달받는다.
  • docker container run(docker run) - 컨테이너 생성 + 실행
    docker run 만 써도 무방하다. container 를 쓰는 이유는 단순 명시하기 위해 쓴다.
실행하게 되면
1) 이미지를 로컬 저장소에서 찾는다. 없다면 기본적으로 도커 허브로 접속하여 검색한다.
2) pull 된 이미지를 이용하여 컨테이너 생성하고 실행시킨다. 실행시 문제가 있다면 exit 상태가 된다. 
  • docker container start - 중지된 컨테이너를 실행

◎ docker container run 옵션

  • -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주소를 등록

★ Dockerfile

  • 컨테이너(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
    1. 위의 파일을 이용하여 xe:1.0 이미지를 만드세요
    1. 그리고 mysql:5.7을 이용하여 root 패스워드를 test123으로 설정하고, 기본 DB 이름도 지정하되 이름을 xe로 하여 컨테이너를 배포하세요. 컨테이너 이름은 db1으로 하세요
    1. xe:1.0 이미지를 이용하여 xe1 컨테이너를 생성하되, "2"에서 만든 db1과 link 시키고 외부에서 8888번 포트 를 컨테이너 80번 포트와 매핑시켜서 배포하세요
    1. 두개의 컨테이너가 정상적으로 배포되었다면 http://211.183.3.112:8888/xe로 접속하면 설치화면으로 들어가게 됩니다. 필요한 내용을 입력하셔서 정상적인 게시판이 보이도록 해 주세요!
  • 만약 이미지 생성이 너~무 오래 걸려서 잘 안된다면 도커허브에 있는 kakaorapa/xe:1.0 이미지를 사용하셔도 됩니다.

[풀이]

    1. 위의 파일을 이용하여 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 .
    1. 그리고 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
    1. 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
    1. 두개의 컨테이너가 정상적으로 배포되었다면 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


3-TIER

  • 일반적으로 웹서비스는 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

  • 네트워크에 연결되지 않음

Network 생성 - 네트워크 대역 자동 설정

  • 가상의 네트워크 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 [컨테이너 이름]

Network 생성 - 네트워크 대역 수동 설정

  • 우리가 원하는 대역의 주소를 지정하여 네트워크 생성하기
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

0개의 댓글