<이론>
- 주제도커 컴포즈를 이용해서 컨테이너를 운영하고 빌드하는 방법을 다룬다.
- docker-compose(도커컴포즈)
- docker-compose를 이용한 컨테이너 실행
- docker-compose 동작 예제
docker-compose(도커컴포즈)
개념
도커의 CI로서 여러 컨테이너를 일괄적으로 정의하고 실행,관리할 수 있는 툴 (각 컨테이너에 대한 명령을 내리면 실행해주는 애)
cf) CI/CD
- CI(지속적인 통합. Continuous Integration) 개발자를 위한 빌드/테스트 자동화 프로세스
- 효과 애플리케이션에 대한 새로운 코드 변경 사항이 정기적으로 빌드 및 테스트되어 공유 리포지토리에 통합되므로 여러 명의 개발자가 동시에 애플리케이션 개발과 관련된 코드 작업을 할 경우 서로 충돌할 수 있는 문제를 해결 가능
- CD(지속적인 서비스 제공/배포. Continuous Delivery/Deployment) 배포 자동화 과정으로서 둘 다 파이프라인의 추가 단계에 대한 자동화 의미로 쓰이거나 얼마나 많은 자동화가 이루어지고 있는지를 설명하기 위해 별도로 사용됨
- 효과 빌드, 테스트 및 배포 단계를 자동화하는 DevOps 방식을 논리적 극한까지 끌어 올립니다. 코드 변경이 파이프라인의 이전 단계를 모두 성공적으로 통과하면 수동 개입 없이 해당 변경 사항이 프로덕션에 자동으로 배포됩니다. 지속적 배포를 채택하면 품질 저하 없이 최대한 빨리 사용자에게 새로운 기능을 제공할 수 있습니다.
효과
하나의 서비스를 운영하기 위해서는 여러 개의 애플리케이션이 동작해야하는데 이러한 컨테이너화된 애플리케이션들을 yaml 파일을 통해 통합 관리할 수 있음
HOW TO
yaml 파일에 문법 작성
Docker compose YAML → docker-compose → 각 컨테이너
- 기본 매번 명령어를 직접 커맨드에 실행해서 컨테이너를 제어 (ex-웹데이터공간을 /var/xx로 마운팅해서 실행해달라.)
- docker-compose yaml(야물) 파일로 작성해서 도커컴포즈한테 요청을 하면 도커컴포즈는 도커명령어로 해석하여 대신 운영해줌
docker-compose를 이용한 컨테이너 실행
도커컴포즈로 컨테이너를 실행하기 위해서는 도커컴포즈가 이해할 수 있는 yaml 파일 문법에 맞춰서 작성해야한다.
yaml 문법
version
compose 버전 지정. (버전에 따라 지원 문법이 다르기 때문)
version:"2"
services
컴포즈를 이용해서 실행할 컨테이너 옵션을 정의 도커컴포즈에게 실행을 요청한 컨테이너에 대해 관리하는 것. 각 컨테이너 구분을 서비스라고 함.
service: webserver: #컨테이너이름1 image: nginx db: #컨테이너이름2 image: redis
build
컨테이너 빌드할 떄 사용
webapp: build : .
image
compose를 통해 실행할 이미지를 지정
webapp: image: centos:7
command
컨테이너에서 실행할 때 추가적인 명령어 지정.
app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" #yarn은 자스형태의 패키지관리자
port(== -p
)
컨테이너가 공개하는 포트를 나열.-p랑 같음
webapp: image: httpd:latest port: - 80 - 8443:443
link
다른 컨테이너와 연계할 때 연계할 컨테이너 지정
webserver: image: wordpress: latest link: db: mysql #webserver 컨테이너는 mysql가 필요하다면 mysql컨테이너의 환경변수나 호스트네임을 알고 있어야 접속가능하므로 이 환경변수들을 가지고 연결해달라고 하는 것
expose
포트를 링크로 연계된 컨테이너에만 공개할 포트 지정
webapp: build: .
volumes
컨테이너에 볼륨을 마운트
webapp: image: httpd volumes: - /var/www/html #/var/www/html 공간에다가 볼륨 마운팅해준다는 것 #볼륨공간이 정의가 되어있고 db_data공간을 var/lib/mysql에다가 wordpress 공간을 var/www/html에다가 볼륨마운트해준다는 것
environment
컨테이너에 적용할 환경변수를 정의
database: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: pass
restart
컨테이너가 종료될 때 적용할 정책
- no : 재시작 되지 않음 (기본값)
- always: 컨테이너를 수동으로 끄기 전까지 항상 재시작됨
- on-failure: 오류가 있을 시에 재시작
database: image: mysql:5.7 restart : always
depends_on
컨테이너 간의 종속성을 지정 (정의한 컨테이너가 실행중이어야 함) 정의한 컨테이너가 먼저 실행된 상태여야 실행가능하도록 종속성을 지정하는 것.
services: web: image: wordpress:latest depends_on: - db db : image: mysql
docker-compose 명령어
실행한 컨테이너들의 상태정보,로그 볼 수 있고 스탑,제거가 가능 docker-compse <command>
docker-compse config docker-compse up docker-compse up -d docker-compse -f /other-dir/docker-compose.yml #다른디렉토리에 있는 docker-compse 파일 동작시켜줄 때 docker-compse ps docker-compse scale 서비스이름=개수 docker-compse run 서비스이름 실행명령어 #추가적인 명령어 docker-compse logs 서비스이름 #특정 서비스의 로그 확인 docker-compse stop docker-compse start docker-compse down
up
컨테이너 생성/시작
ps
컨테이너 목록 표시
logs
컨테이너 로그 출력
run
컨테이너 실행 현재실행중인 서비스에다가 추가 명령어 지정할 떄 사용 exec 커맨드랑 비슷
start
컨테이너 시작
stop
컨테이너 정지
restart
컨테이너 재시작
pause
컨테이너 일시정지
unpause
컨테이너 재개
port
공개 포트 번호 표시
config
구성 확인. docker-compse yaml 파일의 문법 확인해주는 것.
kill
실행중인 컨테이너 강제 정지
rm
컨테이너 삭제
down
리소스 삭제
- --volumes 옵션을 추가하면 도커컴포즈에서 만들어진 볼륨들도 삭제해달라는 옵션
docker-compose 동작 예제
기존에 있는 컨테이너 이미지를 이용한 웹서버 생성 PROCESS 예제
- 서비스 디렉토리 생성 도커컴포즈를 사용할 서비스 디렉토리 생성 서비스디렉토리 이름은 서비스를 떠올리기 쉬운 이름으로 지정
mkdir webserver cd webserver
- docker-compose.yml 생성 문법에 맞춰서 직접 생성
cat > docker-compose.yml version: '3' services: web: image:httpd:latest ports: - "80:80" links: - mysql:db command: apachectl - DFOREGROUND mysql: image: mysql:latest command:mysqld enviroment: MYSQL_ROOT_PASSWORD:pass
- docker-compose 명령어 실행
# 도커컴포즈한테 yml 파일을 기준으로 백그라운드로 실행시켜달라 말하는 것 docker-compose up -d #뒤에 아무것도 안넣었으니까 앞에 만든 디렉토리에 doccker-compose파일을 기준으로 컨테이너 두개가 실행됨. docker-compose ps #그 디렉토리에서 dockercompose ps를 했기때문에 현재 디렉토리에서 실행됐던 컨테이너 정보들만 나와. docker-compose scale mysql=2 #mysql 컨테이너 개수를 2개로 해달라는 것. scale-out,scale-in docker-compose ps docker-compose down #현재 디렉토리에서 동작됐떤 컨테이너들을 완전히 종료시켜달라는 것
컨테이너이미지 빌드부터 운영까지의 예제
- 서비스 디렉토리 생성
mkdir composetest cd composetest
- 빌드를 위한 dockerfile 생성
cat > Dockerfile FROM python:3.7 -alpine #베이스이미지 파이썬3.7 알파인 WORKDIR /code #작업디렉토리 지정. 모든 작업의 데이터들이 저장됨. ENV FLASK_APP=app.py #FLASK가 웹서비스 지원해주니까 해당 웹서버에서 아파치 대신 씀. 그래서 FLask에서의 환경변수 지정1 ENV FLASK_RUN_HOST=0.0.0.0 # FLask에서의 환경변수 지정2 RUN apk add --no-cache gcc musl-dev linux-headers #기본어플리케이션 설치 COPY requirements.txt requirements.txt # 파이썬 베이스이미지에서 필요한 라이브러리 목록을 requirements.txt에 지정하는데 FLASK나 레디스와 연동되어야 하니까 이 파일에 FLASK랑 redis 작성함 컨테이너안으로 복사해서 RUN pip install -r requirements.txt #그 파일을 토대로 pip 명령어로 파이썬 라이브러리로서 설치되는 것. EXPOSE 5000 COPY. . #code디렉토리에다가 애플리케이션의 작업을 복사함. 현재디렉토리에 있는 파이썬 파일부터 시작해서 모든 작업의 파일들이 컨테이너의 code 디렉토리로 복사돼서 실행이 됨. CMD ["flask","run] #그걸 토대로 flask가 동작시키도록 flask를 실행시킴
- docker-compose.yml 생성 도커파일을 가지고 web 컨테이너로 빌드해달라고 말하고 redis는 이미지 실행해달라고 요청하느 ㄴ것 redis는 증가횟수를 저장하기 위한 데이터베이스로 사용하기 위함 두개의 컨테이너는 연동돼서 운영됨.
그러면 컨테이너가 빌드되면서 app.py 파일들을 가져가서 플래스크로 웹서비스가 운영되고 카운팅 하고 화면을 뿌려주게 됨.cat > docker-compose.yml version:"3" services: web: build:. #현재 디렉토리에 있는 도커파일을 기준으로 컨테이너빌드해달라는 것 ports: - "5000:5000" #포트포워딩 redis: image:"redis:alpine"
- docker-compose 명령어 실행 이때 빌드하는 것. 컴포즈가 yaml을 가지고 실행시킴 그럼 컨테이너 빌드 과정이 진행되고 실행된 화면까지 표시됨
docker-compose up
<실습>
- 주제
- docker-compose 설치 방법
- 컨테이너 빌드에서 운영까지를 docker-compose로 구현
- Mysql 데이터베이스를 사용하는 wordpress
docker-compose 설치 방법
윈도우 - 도커데스크탑에 Compose가 포함되어있어서 따로 설치 안해도 됨 리눅스 - root 사용자 아녀도 sudo(su) 명령 이용해서 루트권한 얻어낼 유저면 사용 가능함.리눅스 설치방법 보고 도커컴포즈 설치해야함.
컨테이너 빌드에서 운영까지를 docker-compose로 구현
결과: 웹브라우저로 5000포트로 접속할텐데 접속할 떄마다 증가되는 접속횟수를 html로 보여준다. 그런 프로그램을 도커컴포즈로 배포해서 5000포트로 열어주는 게 목적.
ddddad@I-LUV- MINGW64 ~/Docker $ cd composetest/ ddddad@I-LUV- MINGW64 ~/Docker/composetest $ cat > app.py import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) ddddad@I-LUV- MINGW64 ~/Docker/composetest $ cat app.py import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) ddddad@I-LUV- MINGW64 ~/DOcker/composetest $ cat > requirements.txt flask redis ddddad@I-LUV- MINGW64 ~/Docker/composetest $ cat > Dockerfile # syntax=docker/dockerfile:1 FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP=app.py ENV FLASK_RUN_HOST=0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run"] ddddad@I-LUV- MINGW64 ~/Docker/composetest $ ls app.py Dockerfile requirements.txt ddddad@I-LUV- MINGW64 ~/Docker/composetest $ cat > docker-compose.yml version: "3.9" services: web: build: . ports: - "8000:5000" redis: image: "redis:alpine" ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker-compose up Creating network "composetest_default" with the default driver Building web #1 [internal] load build definition from Dockerfile #1 sha256:b88d515ee99e5844726567cf258d3dcdb746c0e21c43282671856f2b6778b544 #1 transferring dockerfile: 30B 0.1s #1 transferring dockerfile: 320B 0.1s done #1 DONE 0.8s #2 [internal] load .dockerignore #2 sha256:77a4cc4542ca43e3137fa1111bf604b12e7f429721d8beba2e7009ac8444e4d9 #2 transferring context: 2B 0.0s done #2 DONE 0.4s #3 resolve image config for docker.io/docker/dockerfile:1 #3 sha256:ac072d521901222eeef550f52282877f196e16b0247844be9ceb1ccc1eac391d #3 ... #4 [auth] docker/dockerfile:pull token for registry-1.docker.io #4 sha256:446d8cc457dbcaf90acbbc628918ebd3686c84159b3adab53fb5332decadea65 #4 DONE 0.0s #3 resolve image config for docker.io/docker/dockerfile:1 #3 sha256:ac072d521901222eeef550f52282877f196e16b0247844be9ceb1ccc1eac391d #3 DONE 11.3s #5 docker-image://docker.io/docker/dockerfile:1@sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd93e80e2 #5 sha256:48a83027ce1f5c304cb45d91fac69a612cf40aeee970f6f9794eda714e262e35 #5 resolve docker.io/docker/dockerfile:1@sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd93e80e2 0.1s done #5 sha256:24d064a369eda7bc7839b6c1c227eac7212d06ca09a8235a4bed467f8acf180d 528B / 528B done #5 sha256:84495a15555de1a8f4738f58268fa8949547068198f8d0fa2a3e3a693d7f923f 2.37kB / 2.37kB done #5 sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd93e80e2 2.00kB / 2.00kB done #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 0B / 9.94MB 0.2s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 1.05MB / 9.94MB 0.9s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 2.10MB / 9.94MB 1.7s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 3.15MB / 9.94MB 2.8s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 4.07MB / 9.94MB 3.3s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 5.24MB / 9.94MB 3.9s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 6.29MB / 9.94MB 4.5s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 7.34MB / 9.94MB 5.0s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 8.39MB / 9.94MB 5.6s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 9.44MB / 9.94MB 6.0s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 9.94MB / 9.94MB 6.3s #5 sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 9.94MB / 9.94MB 6.3s done #5 extracting sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 #5 extracting sha256:09768fef35f2ee387f57e401ae685727d12d1c70c6fd8545a422850167bf1940 0.5s done #5 DONE 8.1s #6 [internal] load build definition from Dockerfile #6 sha256:b34d399fafd50180b22e2c9a5401d8f3bcf86e4d8dc6b6dd00abb0df3ec93a8d #6 DONE 0.0s #7 [internal] load .dockerignore #7 sha256:a81cd0e2ef5309c82d15f8a1f5756da4548cb2870391411e54c846e9d7acab2f #7 DONE 0.0s #8 [internal] load metadata for docker.io/library/python:3.7-alpine #8 sha256:6aa3fbe2d5daab236c694fe35aaf5e88aa0902955f2d77235216c44ae1323666 #8 ... #9 [auth] library/python:pull token for registry-1.docker.io #9 sha256:7a91a5f528ecf0de2cd665e91903875aaa0805e95153fd4423d02976cc9b034d #9 DONE 0.0s #8 [internal] load metadata for docker.io/library/python:3.7-alpine #8 sha256:6aa3fbe2d5daab236c694fe35aaf5e88aa0902955f2d77235216c44ae1323666 #8 DONE 4.9s #10 [1/6] FROM docker.io/library/python:3.7-alpine@sha256:16aad442678e75021e5c90dfec692fe4881ce9bbd011898a361c9d77a557b229 #10 sha256:bdde7b9b4ddc59625c859b9c508d09542006b5e557931a9ac2a4283dedee39f9 #10 resolve docker.io/library/python:3.7-alpine@sha256:16aad442678e75021e5c90dfec692fe4881ce9bbd011898a361c9d77a557b229 #10 resolve docker.io/library/python:3.7-alpine@sha256:16aad442678e75021e5c90dfec692fe4881ce9bbd011898a361c9d77a557b229 0.2s done #10 ... #13 [internal] load build context #13 sha256:e880f629e8ed22b57cc9812574608e45bfb9162dac381fa7f0b07f8c46285a22 #13 transferring context: 1.09kB 0.1s done #13 DONE 0.4s #10 [1/6] FROM docker.io/library/python:3.7-alpine@sha256:16aad442678e75021e5c90dfec692fe4881ce9bbd011898a361c9d77a557b229 #10 sha256:bdde7b9b4ddc59625c859b9c508d09542006b5e557931a9ac2a4283dedee39f9 #10 sha256:16aad442678e75021e5c90dfec692fe4881ce9bbd011898a361c9d77a557b229 1.65kB / 1.65kB done #10 sha256:3c023a9a706bc2b489441f03159868fc234fdd91c5976ce11e5b842f14f7402b 1.37kB / 1.37kB done #10 sha256:7642396105af8105f9053f1b6cd3c0bbf76b8e4707bb31f27fcfe008d7839604 7.71kB / 7.71kB done #10 sha256:2f22aa6a21a61558542d3c0696535f97d0368789f51a16ee04499d7f3560eb8c 0B / 666.78kB 0.2s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 0B / 11.15MB 0.3s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 0B / 2.80MB 0.5s #10 sha256:2f22aa6a21a61558542d3c0696535f97d0368789f51a16ee04499d7f3560eb8c 666.78kB / 666.78kB 0.9s #10 sha256:2f22aa6a21a61558542d3c0696535f97d0368789f51a16ee04499d7f3560eb8c 666.78kB / 666.78kB 0.9s done #10 sha256:1f39f02670276e9b7a26e21535009d7ac5c4cd05ff118e8f1f46390b7f32d3fe 0B / 230B 1.1s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 1.05MB / 11.15MB 1.8s #10 sha256:1f39f02670276e9b7a26e21535009d7ac5c4cd05ff118e8f1f46390b7f32d3fe 230B / 230B 2.0s done #10 sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 0B / 2.87MB 2.1s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 2.10MB / 11.15MB 2.8s #10 sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 1.05MB / 2.87MB 3.8s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 1.05MB / 2.80MB 4.0s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 3.15MB / 11.15MB 4.7s #10 sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 2.10MB / 2.87MB 6.4s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 4.19MB / 11.15MB 7.4s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 1.05MB / 2.80MB 9.2s #10 sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 2.87MB / 2.87MB 11.6s #10 sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 2.87MB / 2.87MB 11.6s done #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 5.21MB / 11.15MB 11.9s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 6.29MB / 11.15MB 13.3s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 2.10MB / 2.80MB 13.5s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 7.34MB / 11.15MB 15.0s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 8.39MB / 11.15MB 16.9s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 2.80MB / 2.80MB 17.2s #10 sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 2.80MB / 2.80MB 17.2s done #10 extracting sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 #10 extracting sha256:2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8 0.4s done #10 extracting sha256:2f22aa6a21a61558542d3c0696535f97d0368789f51a16ee04499d7f3560eb8c #10 extracting sha256:2f22aa6a21a61558542d3c0696535f97d0368789f51a16ee04499d7f3560eb8c 0.5s done #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 9.44MB / 11.15MB 19.0s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 10.49MB / 11.15MB 20.7s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 11.15MB / 11.15MB 22.1s #10 sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 11.15MB / 11.15MB 22.3s done #10 extracting sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd #10 extracting sha256:c32eec238ec92238b3a24dd3429bf936a019878af114fe639cd6f0a5389466dd 0.9s done #10 extracting sha256:1f39f02670276e9b7a26e21535009d7ac5c4cd05ff118e8f1f46390b7f32d3fe done #10 extracting sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 #10 extracting sha256:a11d774375bfe3f27e3577ef47dcc1073584c596a760f6023f4ef6edb20c19a1 0.5s done #10 DONE 25.9s #11 [2/6] WORKDIR /code #11 sha256:298e1c913c81d32b284061dde33fa0429e7e3d24b16cab4d914c3d09a841a215 #11 DONE 1.2s #12 [3/6] RUN apk add --no-cache gcc musl-dev linux-headers #12 sha256:91f9075ef6369dfcd9f0ee8a0666edc305bc68cc8fc29afcfa0ebdd3be3f30b8 #12 0.819 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz #12 1.841 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz #12 4.711 (1/12) Installing libgcc (11.2.1_git20220219-r2) #12 4.782 (2/12) Installing libstdc++ (11.2.1_git20220219-r2) #12 5.524 (3/12) Installing binutils (2.38-r2) #12 8.898 (4/12) Installing libgomp (11.2.1_git20220219-r2) #12 8.998 (5/12) Installing libatomic (11.2.1_git20220219-r2) #12 9.019 (6/12) Installing gmp (6.2.1-r2) #12 9.379 (7/12) Installing isl22 (0.22-r0) #12 10.10 (8/12) Installing mpfr4 (4.1.0-r0) #12 11.70 (9/12) Installing mpc1 (1.2.1-r0) #12 11.77 (10/12) Installing gcc (11.2.1_git20220219-r2) #12 43.44 (11/12) Installing linux-headers (5.16.7-r1) #12 44.59 (12/12) Installing musl-dev (1.2.3-r0) #12 47.44 Executing busybox-1.35.0-r13.trigger #12 47.46 OK: 135 MiB in 48 packages #12 DONE 49.0s #14 [4/6] COPY requirements.txt requirements.txt #14 sha256:d55f7e525eb6af41cdd86783780402c297b4cdbf9ac7aaf20732edbf11b93328 #14 DONE 0.5s #15 [5/6] RUN pip install -r requirements.txt #15 sha256:8e3de6f0a48e83946f999a63ecdee3acb4914655c843f4c7fd0b973a9464b3dc #15 5.232 Collecting flask #15 5.403 Downloading Flask-2.1.2-py3-none-any.whl (95 kB) #15 5.543 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺??95.2/95.2 KB 642.5 kB/s eta 0:00:00 #15 5.740 Collecting redis #15 5.757 Downloading redis-4.3.1-py3-none-any.whl (241 kB) #15 6.129 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺??241.2/241.2 KB 657.8 kB/s eta 0:00:00 #15 6.271 Collecting click>=8.0 #15 6.286 Downloading click-8.1.3-py3-none-any.whl (96 kB) #15 6.417 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺??96.6/96.6 KB 813.3 kB/s eta 0:00:00 #15 6.692 Collecting importlib-metadata>=3.6.0 #15 6.712 Downloading importlib_metadata-4.11.4-py3-none-any.whl (18 kB) #15 6.852 Collecting Jinja2>=3.0 #15 6.866 Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB) #15 6.995 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺??133.1/133.1 KB 1.1 MB/s eta 0:00:00 #15 7.157 Collecting Werkzeug>=2.0 #15 7.181 Downloading Werkzeug-2.1.2-py3-none-any.whl (224 kB) #15 7.340 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺??224.9/224.9 KB 1.5 MB/s eta 0:00:00 #15 7.448 Collecting itsdangerous>=2.0 #15 7.485 Downloading itsdangerous-2.1.2-py3-none-any.whl (15 kB) #15 7.699 Collecting typing-extensions #15 7.717 Downloading typing_extensions-4.2.0-py3-none-any.whl (24 kB) #15 7.889 Collecting packaging>=20.4 #15 7.908 Downloading packaging-21.3-py3-none-any.whl (40 kB) #15 7.949 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺 40.8/40.8 KB 1.0 MB/s eta 0:00:00 #15 8.016 Collecting async-timeout>=4.0.2 #15 8.031 Downloading async_timeout-4.0.2-py3-none-any.whl (5.8 kB) #15 8.161 Collecting deprecated>=1.2.3 #15 8.190 Downloading Deprecated-1.2.13-py2.py3-none-any.whl (9.6 kB) #15 8.673 Collecting wrapt<2,>=1.10 #15 8.708 Downloading wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl (80 kB) #15 8.770 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺 80.6/80.6 KB 1.4 MB/s eta 0:00:00 #15 8.942 Collecting zipp>=0.5 #15 8.962 Downloading zipp-3.8.0-py3-none-any.whl (5.4 kB) #15 9.761 Collecting MarkupSafe>=2.0 #15 9.804 Downloading MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl (30 kB) #15 10.25 Collecting pyparsing!=3.0.5,>=2.0.2 #15 10.28 Downloading pyparsing-3.0.9-py3-none-any.whl (98 kB) #15 10.34 ?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺?곣봺 98.3/98.3 KB 1.6 MB/s eta 0:00:00 #15 10.97 Installing collected packages: zipp, wrapt, Werkzeug, typing-extensions, pyparsing, MarkupSafe, itsdangerous, packaging, Jinja2, importlib-metadata, deprecated, async-timeout, redis, click, flask #15 13.59 Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.1.2 async-timeout-4.0.2 click-8.1.3 deprecated-1.2.13 flask-2.1.2 importlib-metadata-4.11.4 itsdangerous-2.1.2 packaging-21.3 pyparsing-3.0.9 redis-4.3.1 typing-extensions-4.2.0 wrapt-1.14.1 zipp-3.8.0 #15 13.59 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv #15 13.94 WARNING: You are using pip version 22.0.4; however, version 22.1.1 is available. #15 13.94 You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command. #15 DONE 14.8s #16 [6/6] COPY . . #16 sha256:387a5fa2ddfecd04efdf1c8023ac90feb602133f741deb90892e4a5e661b601e #16 DONE 0.9s #17 exporting to image #17 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00 #17 exporting layers #17 exporting layers 2.3s done #17 writing image sha256:bef471f791482ce949e08f9feee42511224599b0221eb4a89418c3261d4410cb 0.0s done #17 naming to docker.io/library/composetest_web #17 naming to docker.io/library/composetest_web 0.0s done #17 DONE 2.5s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Pulling redis (redis:alpine)... alpine: Pulling from library/redis Digest: sha256:558d0845026fe0bf091a00c0ad647ffacf9df385d780d433ca70661f7276f834 Status: Downloaded newer image for redis:alpine Creating composetest_redis_1 ... Creating composetest_web_1 ... Creating composetest_redis_1 ... done Creating composetest_web_1 ... done Attaching to composetest_redis_1, composetest_web_1 redis_1 | 1:C 31 May 2022 03:38:56.576 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo redis_1 | 1:C 31 May 2022 03:38:56.576 # Redis version=7.0.0, bits=64, commit=00000000, modified=0, pid=1, just started redis_1 | 1:C 31 May 2022 03:38:56.576 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf redis_1 | 1:M 31 May 2022 03:38:56.577 * monotonic clock: POSIX clock_gettime redis_1 | 1:M 31 May 2022 03:38:56.583 * Running mode=standalone, port=6379. redis_1 | 1:M 31 May 2022 03:38:56.583 # Server initialized redis_1 | 1:M 31 May 2022 03:38:56.583 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. redis_1 | 1:M 31 May 2022 03:38:56.584 * The AOF directory appendonlydir doesn't exist redis_1 | 1:M 31 May 2022 03:38:56.584 * Ready to accept connections web_1 | * Serving Flask app 'app.py' (lazy loading) web_1 | * Environment: production web_1 | WARNING: This is a development server. Do not use it in a production deployment. web_1 | Use a production WSGI server instead. web_1 | * Debug mode: off web_1 | * Running on all addresses (0.0.0.0) web_1 | WARNING: This is a development server. Do not use it in a production deployment. web_1 | * Running on http://127.0.0.1:5000 web_1 | * Running on http://172.18.0.3:5000 (Press CTRL+C to quit) web_1 | 127.0.0.1 - - [31/May/2022 03:55:39] "GET / HTTP/1.1" 200 - ctrl^C # 다른 창------------------------------------------------------------------------------------------- C:\Users\ddddad> docker exec -it composetest_web_1 /bin/sh # 배쉬쉘 접속이 안되고 걍 sh로 되길래 curl은 못쓰고 다운받아와서 파일 여는 거로 함.. /code # wget http://127.0.0.1:5000 Connecting to 127.0.0.1:5000 (127.0.0.1:5000) saving to 'index.html' index.html 100% |******************************************************************************************| 39 0:00:00 ETA 'index.html' saved /code # cat index.html Hello World! I have been seen 1 times. #------------------------------------------------------------------------------------------ ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE composetest_web latest bef471f79148 23 minutes ago 182MB redis alpine c3ea2db12504 5 days ago 28.4MB ddddad@I-LUV- MINGW64 ~/Docker/composetest $ vi docker-compose.yml version: "3.9" services: web: build: . ports: - "8000:5000" volumes: - .:/code #현재작업디렉토리가 code고 그 안에 app.py가 있으니까 code 디렉토리를 로컬디렉토리에서 제어할려고 볼륨마운트함 environment: FLASK_ENV: development redis: image: "redis:alpine" ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker-compose up -d #백그라운드모드로 실행 Recreating composetest_web_1 ... Starting composetest_redis_1 ... Starting composetest_redis_1 ... done Recreating composetest_web_1 ... done ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker-compose ps #현재도커컴포즈파일에 의해서 실행된 컨테이너목록을 볼 수 있음 Name Command State Ports ------------------------------------------------------------------------------------- composetest_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp #포트만 열린 상태 composetest_web_1 flask run Up 0.0.0.0:8000->5000/tcp #포트포워딩이 된 상태 ddddad@I-LUV- MINGW64 ~/Docker/composetest $ vi app.py #해서 World 대신 Docker로 바꿔도 볼륨마운트를했기때문에 바로바로 적용되는 걸 확인가능함 ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker-compose scale redis=3 #스케일 인-아웃이 자유로움 The scale command is deprecated. Use the up command with the --scale flag instead. Creating composetest_redis_2 ... Creating composetest_redis_3 ... Creating composetest_redis_3 ... done Creating composetest_redis_2 ... done ddddad@I-LUV- MINGW64 ~/Docker/composetest $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------- composetest_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp composetest_redis_2 docker-entrypoint.sh redis ... Up 6379/tcp composetest_redis_3 docker-entrypoint.sh redis ... Up 6379/tcp composetest_web_1 flask run Up 0.0.0.0:8000->5000/tcp
기존의 yaml 파일 수정해서 적용하기
- 기존 운영중인 컨테이너 중지 실행중인 컨테이너에서 ctrl+c 하기 cf) 실행중인 거 삭제시킬라면 다른 창의 해당 실행중인 컨테이너 디렉토리에서 docker-compose down하면 가능
- 볼륨,환경변수 추가해서 수정 적용
스케일인아웃이 자유롭지만 포트포워딩이 된 컨테이너는 안돼. 왜냐면 정해져있는 포트를 쓰기때문에 확장안돼. 포트충돌이 뜸. 다른 포트를 쓰면 상관없겠지만version: "3.9" services: web: build: . ports: - "8000:5000" volumes: - .:/code #현재작업디렉토리가 code고 그 안에 app.py가 있으니까 code 디렉토리를 로컬디렉토리에서 제어할려고 볼륨마운트함 environment: FLASK_ENV: development #web이란 컨테이너에다가 env 환경변수 알려달라는 것 redis: image: "redis:alpine"
Mysql 데이터베이스를 사용하는 wordpress
mysql 디비랑 wordpress 연동하는 거 wordpress는 mysql을 필요로 하니까! 실제 컨테이너는 워드프레스랑 mysql이 필요하고 두개가 연동되어져서 실행되어야한다.
ddddad@I-LUV- MINGW64 ~/Docker/composetest $ cd ../ ddddad@I-LUV- MINGW64 ~/Docker $ mkdir my_wordpress ddddad@I-LUV- MINGW64 ~/Docker $ cat > docker-compose.yml version: "3.9" services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: #db 실행된 다음에 wordpress 실행되도록 종속성 부여 #그래야 디비에 데이터 축적 가능하니까 depends_on: - db image: wordpress:latest volumes: - wordpress_data:/var/www/html ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: db_data: {} wordpress_data: {} ddddad@I-LUV- MINGW64 ~/Docker $ vi docker-compose.yml ddddad@I-LUV- MINGW64 ~/Docker $ docker-compose up -d Removing docker_wordpress_1 docker_db_1 is up-to-date Recreating a2ddadf3b2fa_docker_wordpress_1 ... Recreating a2ddadf3b2fa_docker_wordpress_1 ... done ddddad@I-LUV- MINGW64 ~/Docker $ docker-compose down --volumes #볼륨까지 삭제 Stopping docker_wordpress_1 ... Stopping docker_db_1 ... Stopping docker_wordpress_1 ... done Stopping docker_db_1 ... done Removing docker_wordpress_1 ... Removing docker_db_1 ... Removing docker_wordpress_1 ... done Removing docker_db_1 ... done Removing network docker_default Removing volume docker_db_data Removing volume docker_wordpress_data
wordpress가 사용하는 공간에 볼륨마운트를 시키는데 그 데이터는 mysql에다가도 쌓이겠지???
wordpress 컨테이너에서 실행되는 데이터는 mysql에 보존되는데 mysql 데이터는 db_data 볼륨에 보존하도록 되어있자나 db_data에 루트계정으로 들어가서 cd /var/lib/docker/volumes/db_data/_data 하면 여기에 mysql 디비데이터가 쌓이고 wordpress컨테이너가 보내주는 데이터도 보존하고 있음.
'DEVOPS > Docker' 카테고리의 다른 글
[따배도] 9장 - 컨테이너간 통신(네트워크) (0) | 2022.06.01 |
---|---|
[따배도] 8강 - 컨테이너 스토리지 관리 (0) | 2022.05.12 |
[따배도] 7강 - 컨테이너 리소스 관리 (0) | 2022.05.12 |
[따배도] 6강 - 컨테이너 사용하기 (0) | 2022.05.12 |
[따배도] 5강 - 컨테이너 Registry (0) | 2022.05.12 |