docker-compose
는 여러 컨테이너를 한번에 관리하기 위해 만들어진 툴입니다. 앞선 예시만 하더라도 3개의 컨테이너 (nginx, flask, mysql)을 운용하기 위해서 상당한 시간과 작업이 들어간 것을 확인할 수 있었습니다. docker-compose
를 통해 조금 더 체계적이고 통합적으로 관리할 수 있는 방법에 대해서 알아 보겠습니다. docker-compose
를 사용하기 위해서는 docker-compose.yml
이라는 파일을 작성해야 합니다. 이 YAML 파일에 사용할 모든 컨테이너와 각 컨테이너들간의 관계를 나타냅니다.
먼저 docker-compose
를 설치합니다.
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
예시로, 웹 사이트에 접속할 때마다, 접속 횟수를 기록하여 보여주는 간단한 웹 사이트를 python flask로 개발해 보겠습니다. 예시에서 flask
와 redis
가 사용될 예정입니다.
먼저 redis에 접속 횟수를 저장하는 flask 앱을 제작해 봅시다.
# 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)
app.py 파일을 이용해 flask 이미지를 만듭니다.
이때 requirements.txt
에는 flask
와 redis
패키지가 들어갑니다.
# Dockerfile
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
COPY app.py app.py
RUN pip install -r requirements.txt
CMD ["flask", "run"]
# requirements.txt
Flask==1.1.2
redis==3.5.3
이제 docker-compose.yaml
파일을 작성해 봅시다.
version: '3'
services: # 모든 컨테이너 리스트
flask:
build: . # 사용할 이미지를 현재 Dockerfile을 이용하여 빌드
ports: # 연결할 포트 (호스트:컨테이너)
- "5000:5000"
volumes: # 연결할 볼륨 (호스트:컨테이너)
- /home:/var/log
redis: # redis
image: "redis:alpine" # 사용할 이미지
version
: 도커 컴포즈 버전을 명시합니다. 현재 1,2,3 버전까지 나왔습니다.services
: 도커 컴포즈가 관리하는 컨테이너 리스트를 지정합니다.flask
: flask 앱을 실행 시킬 web이라는 컨테이너를 선언합니다.build
:docker build .
와 동일합니다.ports
: 호스트와 컨테이너의 네트워크 포트 바인딩을 수행합니다.volumes
: 호스트와 컨테이너의 볼륨 바인딩을 수행합니다.
redis
: redis 앱을 실행할 컨테이너를 명시합니다.image
: web에서와 같이 도커 이미지를build
하지 않고 기존에 존재하는 이미지를 참조합니다.
docker-compose.yaml
은 마치 전체적으로 도커 컨테이너를 어떻게 실행할지 (어떤 이미지를 어떻게, 누구와 무엇을 등) 명시해 놓은 정의서와 같습니다. 이 정의서를 작성한 다음 사용자는 docker-compose up
만 실행하면 나머지는 도커 컴포즈가 알아서 컨테이너를 구성해 줍니다.
도커 컴포즈의 여러가지 기능과 명령이 존재하지만 docker-compose up
명령 하나가 대부분의 문제를 해결해 줍니다.
docker-compose up
# 백그라운드 실행을 위해서는 -d 옵션 추가
docker-compose up -d # for backgroun
docker-compose up
을 실행하면 도커 빌드부터 시작하여 컨테이너 실행, 컨테이너 네트워크/볼륨 연결 등 모든 작업을 docker-compose가 알아서 설정해 줍니다. 여기서 중요한 점은, 도커 컴포즈가 flask에서 redis의 주소를 단순히 redis
라고 참조할 수 있게 해줍니다. (app.py의 약 7번째줄 cache = redis.Redis(host='redis', port=6379)
부분 참조)
이것은 docker-compose에서 컨테이너 redis
를 참조하고 있다는 것을 의미 합니다. 도커 컴포즈가 내부적으로 이름을 기준으로 컨테이너간 참조할 수 있도록 네트워크을 구성해 줍니다. 위의 docker-compose.yml
은 아래의 각각의 도커 명령과 동일합니다.
# redis 실행
docker run --name redis -d redis:alpine
# flask 이미지 빌드
docker build . -t flask
# flask 실행 (redis 네트워크 참조)
docker run --link redis -p 5000:5000 -d flask
--link
라는 옵션은 flask
컨테이너가 redis
컨테이너와 이름으로 통신할 수 있게 설정하는 옵션입니다.
도커 컴포즈는 여러 도커를 편리하게 관리해 주는 툴이기 때문에 대부분의 명령이 기본 docker 명령과 유사합니다.
docker-compose ps
# Name Command State Ports
# --------------------------------------------------------------------------------
# ubuntu_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
# ubuntu_flask_1 flask run Up 0.0.0.0:5000->5000/tcp
docker-compose logs -f flask
docker-compose logs -f redis
docker-compose exec flask pwd
docker-compose build
실행한 docker-compose를 내리기 위해 docker-compose down
명령을 실행합니다.
docker-compose down
# Stopping ubuntu_redis_1 ... done
# Stopping ubuntu_flask_1 ... done
# Removing ubuntu_redis_1 ... done
# Removing ubuntu_flask_1 ... done
# 생성된 모든 컨테이너 삭제
docker rm $(docker ps -aq) -f
https://hub.docker.com/_/mysql 를 참조하여 mysql 서버를 띄울 수 있게 docker-compose.yaml
파일을 작성하여 주세요.
다음과 같이 실행하였을 때, 정상적으로 mysql server에 접근할 수 있어야 합니다.
mysql -h $(hostname -i) -u wordpress -p wordpress
04. 도커실행 고급 - Do it more#2에서 구축한 flask
+ DB
앱을 docker-compose.yml
로 변환해 봅시다.