도커에 대하여4 (docker compose)- 8.22

양승현·2022년 8월 22일
0

docker

목록 보기
7/12

복습 -> compose -> docker swarm cluster (swarm mode > stack)

복습

이미지 만들기 (이미지 자체는 할 수 있는게 없음)

  • 정적 파일
  • 컨테이너를 만들기 위한 환경을 제공
  • 생성된 컨테이너는 이미지의 내용을 그대로 '풀어 놓는 것'과 같으므로 read 할 수 있다. write는 안된다.
  • 생성된 컨테이너는 기본 이미지로 부터 읽을 수 있는 부분과 추가적으로 자체 작성할 수 있는 레이어로 구성된다.
  • commit을 이용하여 동작중인 컨테이너를 이미지로 변환할 수 있다. 하지만 안정성 면에서 떨어져 추천하지는 않는다.
  • Dockerfile을 이용하는 방법을 가장 추천한다.

Dockerfile 명령

FROM

  • 새로 만들 이미지의 base image를 지정

RUN

  • image 자체 각종 패키지 설치, 업데이트와 같은 명령을 전달한다. (여러번 사용 가능하다.)

CMD

  • image가 아닌 이미지에서 컨테이너로 배포될 때 컨테이너에서 실행할 명령
예) 이미지에는 RUN을 이용하여 웹서버를 설치하고(RUN apt install -y apache) CMD를 이용하여 컨테이너로 배포될 때 웹서버 데몬(CMD apache2ctl - DFOREGROUND)를 실행하게 된다

ENTRYPOINT

  • CMD와 동일하게 컨테이너를 시작시킬 때 실행 할 명령
  • 이미지 내에 있는 CMD, ENTRYPOINT의 내용을 docker run을 배포할 때 이미지에 있는 옵션과 docker run에 작성한 옵션이 겹치는 경우 이미지내의 CMD 는 무시된다. ENTRYPOINT 는 둘다 실행된다.

ENTRYPOINT, CMD

  • ENTRYPOINT, CMD는 Dockerfile 내에서 1번만 사용한다. 여러번 작성한다면 마지막에 있는 ENTRYPOINT, CMD가 실행된다.
  • 또한 컨테이너 실행시 전달해야할 명령이 많다면, shell 파일을 미리 작성해서 이미지로 전달하고 컨테이너로 실행할 때 이 쉘 파일을 실행하도록 할 수 있다.

COPY

  • 호스트에 있는 파일이나 디렉터리를 이미지로 전달한다.

ADD

  • "COPY"를 포함, URL에 있는 파일 붙여넣기 가능하다. 압축/패키징 되어 있는 파일을 붙여넣기 할 때에는 압축해제/패키지해제 된 상태로 붙여 넣기 된다.
ADD http://www.test.com/index.php /var/www/html
ADD test.tar /var/www/html
-> a.jpg, index.html, test_dir과 같이 패키지가 풀린상태에서 붙여넣기됨

ENV

  • 이미지에 시스템 환경 변수 추가
USERNAME, PWD, HOSTNAME, SSH_CONNECTION
ENV A="Hello"
컨테이너에서 "env" 명령을 실행하면 A="Hello"가 보인다.

EXPOSE

  • 방화벽에서 허용하고자하는 포트를 지정한다. docker run -p를 이용하여 호스트의 포트와 매핑해 주면 외부에서 해당 포트로 접근이 가능해 진다.

VOLUME

  • 배포되는 컨테이너에 자동으로 특정 볼륨이 연결되도록 하기 위한 설정
VOLUME /var/log -> 컨테이너의 /var/log를 호스트의 임의의 볼룸(ID)와 연결한다.
VOLUME /var/www/html /root -> 컨테이너의 두 디렉토리를 두 볼륨과 각각 연결한다.
VOLUME testvolume:/var/log ->  Host 의 testvolume 과 컨테이너의 /var/log 를 연결한다. 허나, 이와 같이 Host 의 volume 을 지정하는 방식은 해당 이미지를 통해 다수의 컨테이너를 만들때, 다수의 컨테이너들이 동일한 Host 의 volume 을 사용하므로 무결성에 문제가 생긴다. 따라서 위와 같이 Host 의 임의의 볼륨 ID 와 연결하는 방법을 사용해야 무결성의 문제를 해결할 수 있다
좋은 선택이 아님

WORKDIR

  • 작업 결로 지정

ONBUILD

  • 해당 이미지를 생성할 때에는 적용되지 않지만, 해당 이미지를 이용하여 새 이미지를 만들때 적용되는 명령
ONBUILD ADD test.tar /urs/share/nginx/html/
현재 이 이미지를 만들때는 해당 명령이 실행안되므로, test.tar 는 필요없다. 허나, 이 이미지를 가지고, 새 이미지를 만들때는 해당 명령을 실행하므로 test.tar 가 필요하다

이미지 생성을 위한 Dockerfile 빌드

  • 이미지 생성
docker build -t myweb:1.0 .
  • 생성된 이미지를 도커 허브에 올리고 싶다면
docker tag myweb:1.0 yang/myweb:1.0
  • Private Registry 에 올리고 싶다면
docker tag myweb:1.0 211.183.3.112:5000/myweb:1.0
  • 저장소에 이미지 push
docker push yang/myweb:1.0 
--> 사전에 docker login 필요. 정상 로그인 되면 로그인 정보(api주소 + auth정보)가 hom/.docker/config.json 파일에 작성한다.
  • 사설 저장소(private-registry)
docker tag myweb:1.0 211.183.3.111:5000/myweb:1.0
docker push 211.183.3.111:5000/myweb:1.0 
--> 사전에 docker login 필요


COMPOSE

docker COMPOSE 란

  • 1대의 노드에서 동일한 컨테이너를 여러개 만들 수 있다.
HTTP1 -> HTTP2
 |         |
 |         |
db1  ->   db2
동일한 컨테이너는 각기 다른 서버에 연결하는 방법이 좋다. 이를 통해 같은 Port 번호를 사용할 수 있다. 이러한 방법을 stack ( swarm + compose ) 라고 하며, 클러스터 환경에서 이루어진다.
  • compose는 특정 서비스를 제공하기 위하여 컨테이너들의 묶음이라고 할 수 있는 "service" 단위로 배포한다.
  • 기존 docker container run 명령으로 작성했던 환경의 컨테이너를 YAML을 이용하여 구성하는 것
  • 파일의 이름은 docker-compose.yaml 이 기본이며, 다른 이름 사용시 -f 옵션을 통해 사용할 docker compose file 이름을 지정해줘야 한다.

docker-compose.yml 작성

  • docker-conpose.yml 파일 내에는 "version", "services", "networks", "volumes" 네 가지 항목이다. 위의 4가지 항목을 왼쪽 벽에 붙여야 한다.
virsion: "3.5"
service:
  web: #  처음 만들때는 디렉터리이름_web1 , 다음에는 디렉터리이름_web2 등 만들때마다 이름이 바뀐다

  db:

network:
volume:

-> 재 사용이 가능하고 수정이 용이하다.
-> 하위 항목 작성시 들여쓰기 주의해야 함

  • 이전에는 지원 됐으나 지금은 지원되지 않는 옵션

--volumes-from : 컨테이너의 디렉터리와 다른 컨테이너의 디렉터리와 mount 하는 것

실습

docker yaml 파일 작성

  • 디렉토리 생성 후 이동
rapa@rapa:~$ mkdir 0822; cd 0822
  • test를 위한 ymal 파일 생성
rapa@rapa:~/0822$ touch docker-compose.yml
  • 편집기 사용
rapa@rapa:~/0822$ vim docker-compose.yml 
rapa@rapa:~/0822$ cat docker-compose.yml 
version: '3.7'

services:
  web:
    image: httpd
    ports: 
      - "8001:80"
    command: httpd -D FOREGROUND
    depends_on:
      - db
    links:  
      - db:mysql      
  db:
    image: mysql:5.7 
    environment: 
      - MYSQL_ROOT_PASSWORD=test123 
      - MYSQL_DATABASE=testdb
  • 배포하기
rapa@rapa:~/0822$ docker-compose up -d
Creating network "0822_default" with the default driver 
--> 속해 있는 디렉터리의 이름으로 별도의 네트워크가 생성된다.
Creating 0822_db_1 ... done
Creating 0822_web_1 ... done
  • 별도의 네트워크를 위한 기본 네트워크가 생성되고 컨테이너도 생성된다.
  • docker-compose ps 는 docker compose 를 이용해 만든 컨테이너 리스트를 확인할 수 있다
rapa@rapa:~/0822$ docker-compose ps
   Name                Command             State              Ports            
-------------------------------------------------------------------------------
0822_db_1    docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp         
0822_web_1   httpd -D FOREGROUND           Up      0.0.0.0:8001->80/tcp,:::8001
                                                  ->80/tcp         

scale 조정

  • docker-compose.yml 파일 포트 범위 수정
  • 수정을 통해서 동일 컨테이너가 생성되더라도 서로 다른 Host의 Port와 연결된다.
rapa@rapa:~/0822$ vi docker-compose.yml 

    ports:
      - "8001-8002:80"
  • 컨테이너 늘리기
rapa@rapa:~/0822$ docker-compose scale web=2
  • 몇개의 컨테이너를 더 늘릴지 모를 경우 컨테이너 포트만 지정해도 된다.
  • 이를 통해 컨테이너 배포 시 Host의 임의의 Port와 자동 연결된다.
rapa@rapa:~/0822$ vi docker-compose.yml 

    ports:
      - "80"
  • 적용
rapa@rapa:~/0822$ docker-compose up -d
rapa@rapa:~/0822$ dc ps
   Name                Command             State              Ports            
-------------------------------------------------------------------------------
0822_db_1    docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp         
0822_web_1   httpd -D FOREGROUND           Up      0.0.0.0:49153->80/tcp,:::491
                                                   53->80/tcp                  
0822_web_2   httpd -D FOREGROUND           Up      0.0.0.0:49155->80/tcp,:::491
                                                   55->80/tcp                  
  • 스케일 1로 조정
rapa@rapa:~/0822$ docker-compose scale web=1
WARNING: The scale command is deprecated. Use the up command with the --scale flag instead.
Stopping and removing 0822_web_2 ... done
Stopping and removing 0822_web_3 ... done
rapa@rapa:~/0822$ dc ps
   Name                Command             State              Ports            
-------------------------------------------------------------------------------
0822_db_1    docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp         
0822_web_1   httpd -D FOREGROUND           Up      0.0.0.0:49153->80/tcp,:::491
                                                   53->80/tcp  

Directory & p 옵션

  • 새로운 디렉터리 생성 후 이동
rapa@rapa:~/0822$ mkdir test1; cd test1
  • docker0compose.yml 파일 현재 디렉터리로 카피
rapa@rapa:~/0822/test1$ cp ../docker-compose.yml .
rapa@rapa:~/0822/test1$ dc up -d
Creating network "test1_default" with the default driver
Creating test1_db_1 ... done
Creating test1_web_1 ... done
rapa@rapa:~/0822/test1$ dc ps
   Name                 Command             State              Ports           
-------------------------------------------------------------------------------
test1_db_1    docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp        
test1_web_1   httpd -D FOREGROUND           Up      0.0.0.0:49156->80/tcp,:::49
                            
					 156->80/tcp       

-p

  • 다른 디렉터리에 명령을 내릴 수 있다.
  • 0822 디렉터리에 있는 컨테이너 네트워크 삭제
rapa@rapa:~/0822/test1$ docker-compose -p 0822 down

컨테이너 삭제

  • 현재 위치 컨테이너, 네트워크 삭제
rapa@rapa:~/0822/test1$ docker-compose down

실습2

네트워크 정의

  • 새로운 네트워크 생성
rapa@rapa:~/0822/test1$ docker network create test1net
1c8293fa547bc2fe88814aaae9236d4f56a0b8209191cf3cfed450404572c10e
  • 테스트를 위하여 임의의 컨테이너를 생성하고 기 생성된
rapa@rapa:~/0822/test1$ docker container run -it --name centos01 --net test1net centos:7
[root@dc9b60904ada /]# 
  • 인터넷 연결 확인
[root@dc9b60904ada /]# ping www.google.com -c 3
PING www.google.com (142.250.196.132) 56(84) bytes of data.
64 bytes from nrt12s36-in-f4.1e100.net (142.250.196.132): icmp_seq=1 ttl=110 time=32.5 ms
64 bytes from nrt12s36-in-f4.1e100.net (142.250.196.132): icmp_seq=2 ttl=110 time=32.6 ms
64 bytes from nrt12s36-in-f4.1e100.net (142.250.196.132): icmp_seq=3 ttl=110 time=33.8 ms

docker compose 파일에 network 정의

rapa@rapa:~/0822/test1$ vi docker-compose.yml 
rapa@rapa:~/0822/test1$ cat docker-compose.yml 
version: '3.7'

services:
  web:
    image: httpd
    ports: 
      - "80"
    command: httpd -D FOREGROUND
    depends_on:
      - db
    links:  
      - db:mysql 
    networks:
      - test1net   --> 네트워크 test1net 사용
  db:
    image: mysql:5.7 
    environment: 
      - MYSQL_ROOT_PASSWORD=test123 
      - MYSQL_DATABASE=testdb
    networks:
      - test1net   --> 네트워크 test1net 사용
networks: 
  test1net: 
    external: true   --> 새로 test1_test1net이 만들어 지는것이 아니라 기존 test1net에 연결된다.
  • 네트워크를 그냥 정의만 하면 디렉터리 이름 + 작성한 이름의 새 network 가 생성된다. 이때, external 옵션을 사용하면, 해당 이름의 새 네트워크 생성이 아닌 기존에 생성된 network 를 활용하게 해줄 수 있다.
rapa@rapa:~/0822/test1$ docker-compose up -d
Creating test1_db_1 ... done
Creating test1_web_1 ... done

볼륨 정의하기

  • 기존 볼륨 활용 가능(네트워크와 동일)
  • 만약 지정하지 않는다면 디렉터리 이름을 이용하여 신규 생성한다.
web:
  volumes:
    - testvolume1:/var/www/html -> 0822_ testvolume1과 컨테이너의 /var/www/html이 연결

volumes:
  testvolume1L -> 0822_testvolume1 이 생성된다
    external: true -> 기존에 만들어둔 testvolume1을 사용한다.
  • docker-compose ps를 이용하면 배포한 컨테이너만 확인할 수 있다.
  • docker container run으로 생선한 컨테이너는 docker-compos ps로 확인할 수 없다

vulume 생성 및 연결하기

  • 볼륨을 생성하고 web 컨테이너에 연결해보자
    volumes:
      - testvol2:/usr/local/apache2/htdocs
  • 위 사진 처럼 volume 에 external 옵션을 true 로 하면 기존의 volume 을 사용하게 된다.

volume 사용 방법

  1. nfs -> 디렉터리 마운트
  2. iscsi -> 스토리지에서 volume을 생성하고 이를 컨테이너 /dev/sda*과 같은 형태로 연결
  3. tmpfs -> 디스크가 아니라 RAM 에 저장되는 것으로 영구 보관이 불가능 하다

1. nfs 방식 사용

  • 디렉터리 내에 파일을 생성하고 아래와 같이 yaml 파일에 web 서비스에 volume을 추가한다.
   volumes:
      - testvol2:/usr/local/apache2/htdocs
      - /home/rapa/0822/test1/shared:/root
  • docker container exec test1_web_1 ls /root 명령어를 통해 생성 컨테이너의 내용을 확인하게 되면 test.txt가 존재한다.

extend 옵션

  • extend 옵션은 yaml 파일을 추가적으로 만들거나 하나의 yaml 내에서 추가 컨테이너 내에 기본 내용을 작성하고, 이를 다른 파일이나 서비스에서 상속하여 사용하는 방법이다
  • 주로, 두 개의 파일을 만들어 두고, 이를 상속받는 방법을 사용한다
rapa@rapa:~/0822/test2$ touch docker-compose.yml extend-compose.yml
  • docker-compose.yml 파일
rapa@rapa:~/0822/test2$ vi docker-compose.yml 

version: '3.7'
services:
  web:
    extends:
      file: extend-compose.yml
      service: testweb
  • extend-compose.yml 파일
rapa@rapa:~/0822/test2$ vi extend-compose.yml 

version: '3.7'
services:
  testweb:
    image: httpd
    ports:
      - "80"

배포하기

  • 두 가지 yaml 파일을 모두 사용하여 배포 해야 한다
docker-compose -f docker-compose.yml -f extend-compose.yml up -d

이미지 지정하기

  • docker-compose.yml과 Dockerfile이 같이 있다면 build: . 을 사용하여 현재 디렉터리의 Dockerfile을 이용해 이미지를 생성하여 사용한다.
 - docker-compose.yml
 - Dockerfile

 version: '3.7'
 services:
   web:
     build: .
     image: myweb:1.0

실습

  • 미리 생성해둔 network(test1net), volume(testvol2)을 활용하여 외부에 워드프레스 서비스를 제공한다. 단, db의 /var/lib/mysql은 testvol2에 마운트 된다. 또한 워드프레스는 외부 노출시 8001~8009를 활용한다.

quiz

  1. mkdir 0822/testlab을 만든다.
  2. 해당 디렉터리 내에서 Dockerfile을 생성하여 이미지 testweb:1.0을 생성한다.
    이미지는 아래의 내용을 포함해야 한다.
 베이스 이미지 => ubuntu:18.04
 설치 패키지 -> nginx를 설치한다.
 0822/testlab에 index.html 파일을 curl을 이용하여 간단히 생성하고 해당 파일을 nginx의 기본 웹 폼디렉터리에 올린다.
 80번 포트가 열려 있어야 하며, 컨테이너로 배포시에는 자동으로 apache2가 실행되어야 한다.
  1. docker-compose 파일을 작성한다. 아래 내용을 포함해야한다.

web

web -> testweb:1.0을 사용 
변수 : DB 이름 DB_NAME -> testdb, DB_USER -> root, DB_PASSWORD -> test123
(나중에 docker container exec testlab_web_1 env하면 위의 정보가 보여야 한다.)
외부 노출시 자신의 80번 포트를 호스트의 8881~8889를 사용한다.

db

 db -> mysql:5.7
 변수 : MYSQL_ROOT_PASSWORD -> test123, MYSQL_DATABASE -> testdb
 두 서비스 모두 (미리 만들어두어야 함)testnetwork1에 연결 되어야 한다.
 db는 미리 생성해 두었던 testvolume1에 연결 되어야 하는데, /var/lib/mysql로 마운트 된다
  1. docker container run 을 활용하여 cadvisor를 설치하고 이를 통해 앞서 만들어 두었던 컨테이너들을 확인할 수 있어야 한다. 물론 cadvior도 testnetwork1에 연결되어 있어야 한다.
  2. 생성된 container는 linux 재부팅시 자동으로 활성화 해야 한다.

해설

  1. mkdir 0822/testlab을 만든다.
rapa@rapa:~$ cd 0822; mkdir testlab; cd testlab
  1. 해당 디렉터리 내에서 Dockerfile을 생성하여 이미지 testweb:1.0을 생성한다.
rapa@rapa:~/0822/testlab$ vi Dockerfile

FROM ubuntu:18.04
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx
EXPOSE 80
ADD index.html /var/www/html/index.html

CMD ["nginx", "-g", "daemon off;"]
  1. docker-compose 파일을 작성한다. 아래 내용을 포함해야한다.
rapa@rapa:~/0822/testlab$ docker network create testnetwork1
a07413eccbd94f03965db91b10ad56148ddd9e13a06baac261a74f63f62e1f16
rapa@rapa:~/0822/testlab$ docker volume create testvolume1
testvolume1
rapa@rapa:~/0822/testlab$ vi docker-compose.yml

version: '3.7'

services:
  web:
    build: .
    environment:
      - DB_NAME=testdb
      - DB_USER=root
      - DB_PASSWORD=test123
    networks:
      - testnetwork1
    ports:
      - "8881-8889:80"
    depends_on:
      - db
    links:
      - "db:mysql"
    restart: always
  db:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=test123
      - MYSQL_DATABASE=testdb
    networks:
      - testnetwork1
    volumes:
      - testvolume1:/var/lib/mysql
    restart: always
networks:
  testnetwork1:
    external: true
volumes:
  testvolume1:
    external: true
rapa@rapa:~/0822/testlab$ docker-compose up -d
rapa@rapa:~/0822/testlab$ docker-compose ps

[결과]

  1. docker container run 을 활용하여 cadvisor를 설치하고 이를 통해 앞서 만들어 두었던 컨테이너들을 확인할 수 있어야 한다. 물론 cadvior도 testnetwork1에 연결되어 있어야 한다.
rapa@rapa:~/0822/testlab$ docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=9559:8080 --detach=true --name=cadvisor google/cadvisor:latest

  1. 생성된 container는 linux 재부팅시 자동으로 활성화 해야 한다.
rapa@rapa:~/0822/testlab$ docker container exec testlab_web_1 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f1edfd466c55
DB_NAME=testdb
DB_USER=root
DB_PASSWORD=test123
HOME=/root

0개의 댓글