복습 -> compose -> docker swarm cluster (swarm mode > stack)
이미지 만들기 (이미지 자체는 할 수 있는게 없음)
- 정적 파일
- 컨테이너를 만들기 위한 환경을 제공
- 생성된 컨테이너는 이미지의 내용을 그대로 '풀어 놓는 것'과 같으므로 read 할 수 있다. write는 안된다.
- 생성된 컨테이너는 기본 이미지로 부터 읽을 수 있는 부분과 추가적으로 자체 작성할 수 있는 레이어로 구성된다.
- commit을 이용하여 동작중인 컨테이너를 이미지로 변환할 수 있다. 하지만 안정성 면에서 떨어져 추천하지는 않는다.
- 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 가 필요하다
- 이미지 생성
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 필요
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
네트워크 정의
- 새로운 네트워크 생성
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 사용 방법
- nfs -> 디렉터리 마운트
- iscsi -> 스토리지에서 volume을 생성하고 이를 컨테이너 /dev/sda*과 같은 형태로 연결
- 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를 활용한다.
- mkdir 0822/testlab을 만든다.
- 해당 디렉터리 내에서 Dockerfile을 생성하여 이미지 testweb:1.0을 생성한다.
이미지는 아래의 내용을 포함해야 한다.베이스 이미지 => ubuntu:18.04 설치 패키지 -> nginx를 설치한다. 0822/testlab에 index.html 파일을 curl을 이용하여 간단히 생성하고 해당 파일을 nginx의 기본 웹 폼디렉터리에 올린다. 80번 포트가 열려 있어야 하며, 컨테이너로 배포시에는 자동으로 apache2가 실행되어야 한다.
- 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로 마운트 된다
- docker container run 을 활용하여 cadvisor를 설치하고 이를 통해 앞서 만들어 두었던 컨테이너들을 확인할 수 있어야 한다. 물론 cadvior도 testnetwork1에 연결되어 있어야 한다.
- 생성된 container는 linux 재부팅시 자동으로 활성화 해야 한다.
해설
- mkdir 0822/testlab을 만든다.
rapa@rapa:~$ cd 0822; mkdir testlab; cd testlab
- 해당 디렉터리 내에서 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;"]
- 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
[결과]
- 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
- 생성된 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