์ Docker-compose๋ฅผ ์ฌ์ฉํ ๊น? - TIL230615
๐ KDT WEEK 11 DAY 4 TIL
- Docker-compose
- ์ค์ต 1 - Docker-compose ํ์ผ์ด ์์ ๋
- ์ค์ต 2 - Docker-compose ํ์ผ์ด ์์ ๋
๐ฅ Docker-compose
docker-compose.yaml : ๋ค์์ ๋์ปค ์ปจํ ์ด๋๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ํ๊ฒฝ์ค์ ํ์ผ
๊ฐ๋ณ Container๋ฅผ ๋ฐ๋ก ๊ด๋ฆฌํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ์์ฐ์ฑ์ด ๋๋ค.
ํ์ผ์ ๊ฐ ์ปจํ ์ด๋๋ณ๋ก ์ด๋ฆ๊ณผ ํฌํธํฌ์๋ฉ, ๋์ปค ๋ณผ๋ฅจ, ํ๊ฒฝ๊ณผ ๋คํธ์ํฌ ๊ตฌ์ฑ ๋ฑ ํ๋ฒ์ ๊ธฐ์ ํด๋๋ค๊ณ ์๊ฐํ๋ฉด ํธํ๋ค.
๋ฐ๋ผ์ ํ๋ง๋๋ก ์ฌ๋ฌ ๊ฐ์ ๋์ปค ์ปจํ ์ด๋๋ก ๊ตฌ์ฑ๋ ํ๋์ ์ฑ์ ๊ตฌ์ฑํ ๋์๋ ๊ต์ฅํ ํธ๋ฆฌํ ํ์ผ์ด๋ค.
๊ทธ ๋ถ๋ถ์ ์ค์ต์ผ๋ก ์ง์ ๋น๊ตํด๋ณด๊ฒ ๋ค.
docker volume๋ ๊ธฐ์ ๋์ด ์๋ค.
์ด์ ๊ธ์์ ๋ฐฐ์ ๋ ๋ด์ฉ์ ์กฐ๊ธ ์ถ๊ฐํ์๋ฉด,
์ด ํ์ผ์ docker volume ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํด ์ด๋ป๊ฒ ๋ง์ดํธ๋ฅผ ํ ๊ฒ์ธ์ง์ ๋ํ ๋ด์ฉ๋ ๊ธฐ์ ๋์ด ์๋ค.

docker-compose.yaml์ ๋ณด๋ฉด, volumes: ํญ๋ชฉ์์ docker volume ๋ง์ดํธ์ ๋ํด ์ ํ์๋ค.
AIRFLOW_PROJ_DIR์ airflow๊ฐ ์ธํ ๋ ํด๋๋ฅผ ์๋์ผ๋ก ์ง์นญํ๋ค.
๋ช ๋ น์ด
- docker-compose build : build ํค๋ก ์ง์ ๋ ์ด๋ฏธ์ง๋ค ๋์์ผ๋ก ๋น๋
- docker-compose pull : image ํค๋ก ์ง์ ๋ ์ด๋ฏธ์ง๋ค ๋์์ผ๋ก docker hub์์ ๊ฐ์ ธ์ค๊ธฐ
- docker-compose images : docker-compose๋ก ์คํ๋ ์ปจํ ์ด๋๊ฐ ์ด๋ค ์ด๋ฏธ์ง๋ก ์คํ๋์๋์ง ๋ฆฌ์คํธ ์ถ๋ ฅ
- docker-compose push : ํ๋ฒ์ docker hub๋ก push(๊ถํํ์)
- docker-compose up : ์ด๋ฏธ์ง๋ฅผ buildํ๊ฑฐ๋ ๋ฐ์์ค๊ณ , ๋์ปค ์ปจํ ์ด๋๋ฅผ ์คํํ๊ณ ์์ํ๋ค.( build + pull + start )
- docker-compose down : ์คํํ ๋ชจ๋ ๋์ปค ์ปจํ ์ด๋๋ค์ ํ๋ฒ์ ๋ฉ์ถ๊ณ (stop) ์ญ์ (rm)๊น์ง ์งํ
- docker-compose ls : docker-compose ๊ทธ๋ฃน๋ณ๋ก ๋ฆฌ์คํธ
- docker-compose ps : docker-compose๋ก ์คํ๋ docker container๋ค์ ์ํ ์ถ๋ ฅ
๐ฆ ๋ค์์ Container๋ก ๊ตฌ์ฑ๋ ์์ ํ๋ก๊ทธ๋จ ์คํํด๋ณด๊ธฐ
๋ณธ ์ค์ต์ ๋์ปค ์์ ๋ก ์ ๊ณต๋๋ vote-application์ ํ ๋๋ก ์ค์ตํ์๋ค.
https://github.com/dockersamples/example-voting-app
GitHub - dockersamples/example-voting-app: Example distributed app composed of multiple containers for Docker, Compose, Swarm, a
Example distributed app composed of multiple containers for Docker, Compose, Swarm, and Kubernetes - GitHub - dockersamples/example-voting-app: Example distributed app composed of multiple containe...
github.com
์ค์ต์ ์งํํ๊ธฐ ์ ์ ๋์ปค ์ปจํ ์ด๋์ ์ด๋ฏธ์ง๋ฅผ ์ ๋ฆฌํด๋๋ ๊ฒ์ ์ถ์ฒํ๋ค.
# ๋์ปค ํด๋ฆฐ์
docker container rm -f $(docker container ls -aq)
docker image rm -f $(docker image ls -q)
์ ์์ ํ๋ก๊ทธ๋จ์ ๋ํด ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ์๋ฉด, ์ด 5๊ฐ์ ์ปจํ ์ด๋๋ก ๊ตฌ์ฑ๋๋ ํ๋ก๊ทธ๋จ์ด๋ค.
vote, result, worker, redis, postgres
vote์ result๋ front-end๋ก์จ ํฌํ ํ๋ฉด๊ณผ ํฌํ ๊ฒฐ๊ณผํ๋ฉด์ ์ ๊ณตํ๊ณ , postgres๋ ํฌํ ๊ฒฐ๊ณผ DB ์ญํ ์ ํ๋ค.
vote > redis > worker > postgres > result ์์๋ก ๋์ํ๋ค๊ณ ๋ณด๋ฉด ์ฝ๋ค.
์ผ๋จ ๋ค์ฏ๊ฐ์ ์ปจํ ์ด๋๋ฅผ ํ๋๋ก ๊ตฌ์ฑํด์ค ๋คํธ์ํฌ๋ฅผ ํ๋ ๋ง๋ค์ด์ผ ํ๋ค.
docker network create mynetwork
mynetwork ๋ผ๋ ์ด๋ฆ์ผ๋ก ๋คํธ์ํฌ๋ฅผ ํ๋ ๊ตฌ์ฑํ๋ค.
์ด ๋คํธ์ํฌ๋ฅผ ์ธ๊ธํ ๋ค์ฏ๊ฐ์ ์ปจํ ์ด๋๋ฅผ runํ๊ฒ ๋ ๋ ์ต์ ์ผ๋ก ์ง์ ํด์ฃผ๋ฉด ๋๋ค.
๋ค์ฏ๊ฐ์ ์ปจํ ์ด๋๊ฐ ํ์ํ๋ฏ๋ก ๋ค์ฏ๋ฒ์ docker run์ด ํ์ํ๋ค.
# Docker file์ ์์น๋ฅผ ์๋ ค ๋์ปค๋ฅผ ๋น๋
docker build -t vote ./vote
docker build -t result ./result
docker build -t worker ./worker
docker run -d --name=vote -p 5001:80 --network mynetwork vote
docker run -d --name=result -p 5002:80 --network mynetwork result
docker run -d --name=worker --network mynetwork worker
# ๊ณต์ ์ด๋ฏธ์ง์ ๊ฒฝ์ฐ run์ ํตํด ์ด๋ฏธ์ง ๋ค์ด๋ก๋
docker run -d --name=redis --network mynetwork redis
docker run --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres
postgres์ ๊ฒฝ์ฐ ์คํํ๋ฉด์ ๋น๋ฐ๋ฒํธ ์ค์ ์ด ํ์ํ๋ฏ๋ก ์กฐ๊ธ ๋ช ๋ น์ด๊ฐ ๋ค๋ฅด๋ค.
๋๋ vote๋ฅผ 5001 ํฌํธ๋ก, result๋ฅผ 5002 ํฌํธ๋ก ์ด์ด๋์๋ค. ์ด ๋ถ๋ถ์ ์์ ๋ค.
์คํ์ด ์๋ฃ๋๋ฉด postgres ์ปจํ ์ด๋๊ฐ ๊ตฌ๋๋๊ณ ์์ ๊ฒ์ด๋ค.
์๋ก์ด ํฐ๋ฏธ๋์ ์ด์ด docker ps๋ฅผ ํด๋ณด๋ฉด 5๊ฐ์ ์ปจํ ์ด๋๊ฐ ์ด๋ ค์์ด์ผ ํ๋ค.
์ด์ ์ด์๋ ํฌํธ๋ฅผ ํตํด ๋ก์ปฌํธ์คํธ๋ก ์ ์ํด๋ณด์.
localhost:5001์ ์ ์ํ๋ฉด vote์ ์ ์๋๊ณ , ํด๋ฆญํด์ ํฌํ๋ ํ ์ ์๋ค.
localhost:5002์ ์ ์ํ๋ฉด result ํ๋ฉด์ด ๋ณด์ด๊ณ , ํฌํ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์๋ ์๋ค.
ํ์ง๋ง ํฌํ ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋ก๋ฐ๋ก ํฌํ ๊ฒฐ๊ณผ์ ๋ฐ์๋์ง๋ ์๋๋ค.
์๋ํ๋ฉด postgres ์ถ๊ฐ์ค์ ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ด๋ค.. ์ด ๋ถ๋ถ์ด ์ง๊ธ ์ค์ต์์ ์ค์ํ ๊ฑด ์๋๋ฏ๋ก ๋์ด๊ฐ๊ฒ ๋ค.
๐ฉ ์ด๋ฒ์๋ docker-compose๋ก ๊ฐ๋จํ๊ฒ ์ฐ๊ฒฐํด๋ณด๊ธฐ
์์ ํ๋ก๊ทธ๋จ์๋ docker-compose ํ์ผ์ ์ ๊ณตํ์ง๋ง, ์๋ก์ด docker-compose ํ์ผ์ ๊ฐ๋จํ๊ฒ ๊ตฌ์ฑํ์๋ค.
services:
vote:
build: ./vote
# use python rather than gunicorn for local dev
command: python app.py
ports:
- "5001:80"
result:
build: ./result
# use nodemon rather than node for local dev
entrypoint: nodemon server.js
ports:
- "5002:80"
worker:
build: ./worker
redis:
image: redis:alpine
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
docker-compose ํ์ผ์ services: ๋ฐ์ผ๋ก ๊ฐ๊ฐ์ ๊ตฌ์ฑํ ์ปจํ ์ด๋๋ค์ ์์ฑํ๊ฒ ๋๋ค.
vote, result, worker, redis, db(postgres)๋ก ์๊น์ ๊ฐ์ด 5๊ฐ์ ์ปจํ ์ด๋๋ฅผ ์์ฑํ๋ค.
vote, result, worker๋ build: ๋ฅผ ํตํด ๊ฐ๊ฐ์ docker file ์์น๋ฅผ ์๋ฆฐ๋ค.
vote์ result๋ ํฌํธํฌ์๋ฉ์ด ํ์ํ์ผ๋ port: ๋ฅผ ์ฌ์ฉํ๋ค.
command: ์ entrypoint: ๋ docker file์ ์์ฑ๋ CMD์ ENTRYPOINT๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ ๋ ์ฌ์ฉํ๋ค.
redise์ db๋ ๊ณต์ ์ด๋ฏธ์ง์ด๋ฏ๋ก image: ๋ฅผ ์ฌ์ฉํด์ ์ด๋ค ์ด๋ฏธ์ง๋ฅผ docker hub์์ ๋ฐ์์ฌ์ง ์์ฑํ๊ณ ,
postgres์ ๊ฒฝ์ฐ ํ๊ฒฝ๋ณ์๊ฐ ํ์ํ์ผ๋ environment: ๋ฅผ ํตํด ํด๋น ์ฌํญ์ ์์ฑํ๋ค.
์ด๋๋ก ์์ ํ๋ก๊ทธ๋จ ํด๋์ docker-compose.mac.yml ํ์ผ๋ก ์ ์ฅํ์๋ค.
์ด์ ๋ ์คํํ๋ ์ผ๋ง ๋จ์๋ค!
์ผ๋จ ์๊น ์ค์ตํ๋ ๋ด์ฉ์ด ์๋ค๋ฉด ์ปจํ ์ด๋์ ์ด๋ฏธ์ง ์ฒญ์๋ฅผ ํด๋์.
# ๋์ปค ํด๋ฆฐ์
docker container rm -f $(docker container ls -aq)
docker image rm -f $(docker image ls -q)
๊ทธ๋ฆฌ๊ณ ์์ ํ๋ก๊ทธ๋จ ํด๋์์ ๋ค์์ ๋ช ๋ น์ด๋ง ์ ๋ ฅํ๋ฉด ๋๋ค.
# docker-compose up
docker-compose -f docker-compose.mac.yml up
ํ์ผ์ ์ด๋ฆ์ด docker-compose.yml ์ด๊ฑฐ๋ docker-compose.yaml ์ด๋ผ๋ฉด docker-compose up ์ผ๋ก ์ถฉ๋ถํ๋ค.
ํ์ง๋ง ๋๋ ์๋ก์ด docker-compose ํ์ผ์ ๋ฃ๊ณ ์ด๋ฆ๋ ๋ฐ๊ฟง์ผ๋ ์์ ๋ช ๋ น์ด์ฒ๋ผ, -f ์ต์ ์ ์ฌ์ฉํด ์ด๋ฆ์ ์๋ ค์ผํ๋ค.
๋ฐ๋ก ๋ก์ปฌํธ์คํธ๋ก ์ ์ํด์ ์๋ํ๋์ง ํ์ธํด๋ณด์.
์ฒซ ๋ฒ์งธ ์ค์ต์์ ์ฌ์ฉํ๋ network๊ฐ ์๋ต๋๋ ๋์ํ๋ ์ด์ ๋, docker-compose์์๋ ์๋์ผ๋ก ํ๋์ ๋คํธ์ํฌ๋ก ๋ฌถ์ด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
services์ ์ค ์ด๋ฆ์ผ๋ก ํธ์คํธ ์ด๋ฆ์ด ์์ฑ๋์ด ์ด๋ฆ์ ๋ด๋ถ IP๋ก ๋ณํํด์ฃผ์ด, docker๋ผ๋ฆฌ ๋คํธ์ํฌ ์ฐ๊ฒฐ๋๋ค.
โ๏ธ docker-compose.yml ๋ด์ฉ ์์๋ณด๊ธฐ
0. docker-compose.yml ํ์ผ์์ airflow ํ๊ฒฝ๋ณ์ ์ค์ ํ๊ธฐ
x-airflow-common:
&airflow-common
image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.5.1}
environment:
&airflow-common-env
AIRFLOW_VAR_DATA_DIR: /opt/airflow/data
AIRFLOW__API__AUTH_BACKENDS: 'airflow.api.auth.backend.basic_auth,airflow.api.auth.backend.session'
์ ๋ด์ฉ์ ๋ด airflow์ docker-compose.yml ๋ด์ฉ ์ผ๋ถ์ด๋ค.
environment์ ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ ์ ์๋๋ฐ, ํฌ๊ฒ AIRFLOW ๋ค์ ์ธ๋๋ฐ ๊ฐ์๋ก ๊ตฌ๋ถ๋๋ค.
- AIRFLOW_ : airflow์ variables ๊ฐ์ ๋ณ์๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋ ์ ์๋ค.
- AIRFLOW_VAR_๋ณ์์ด๋ฆ : variables์ : ๋ค์ ํด๋นํ๋ ๋ด์ฉ์ ๋ณ์์ด๋ฆ์ ์ ์ฅํ๋ค.
- AIRFLOW__ : airflow.cfg ์ ํด๋น ์น์
์ ๊ฐ์ ๋ณ๊ฒฝํ๋ค.
- AIRFLOW__API__AUTH_BACKENDS : airflow.cfg์ api ์น์ ์ ํด๋นํ๋ auth_backend ๊ฐ์ ๋ณ๊ฒฝํ๋ค.
airflow.cfg์ ๊ฒฝ์ฐ AIRFLOW ๋ค์ ์ธ๋๋ฐ๊ฐ ๋ ๊ฐ, ํด๋น ์น์ ๋ค์์ผ๋ก ์ธ๋๋ฐ๊ฐ ๋ ๊ฐ์ธ ๊ฒ์ ์ฃผ์ํด์ผํ๋ค.
์ด ํ๊ฒฝ๋ณ์๋ค์ docker compose up์ ํ๋ฉฐ ์๋์ผ๋ก ์ค์ ๋์ง๋ง, Airflow ์น UI์ ๊ฐ์ ์ธ๋ถ์์ ํ์ถ๋์ง ์๋๋ค.
1. build: ๋น๋ ๊ด๋ จ ์ ๋ณด๋ฅผ ๋๊ธด๋ค.
ex)
worker:
build: ./worker
worker:
build:
context: ./woker
dockerfile : Dockerfile.dev
arg:
ENVIRONMENT: development
- context: ๋์ปค ํ์ผ์ ์์น๋ฅผ ๋๊ฒจ ๋น๋ (์ฒซ ๋ฒ์งธ ์์์ฒ๋ผ ์ค์ฌ์ฐ๊ธฐ๋ ํจ)
- dockerfile: ๋์ปคํ์ผ์ ์ด๋ฆ(Dockerfile.yml์ด ์๋ ๋ค๋ฅธ ์ด๋ฆ์ผ ๋ ์ฌ์ฉ)
- args: ํ๊ฒฝ๋ณ์ ๋๊ธฐ๊ธฐ
2. depends_on: ์ด๋ค ์ปจํ ์ด๋๊ฐ ๋์ํ ํ์ ํด๋น ์ปจํ ์ด๋๋ฅผ ์คํํ๋๋ก ๋ช ๋ น
ex)
worker:
depends_on:
db:
conditions: service_healthy
condition์ผ๋ก ๊ฐ๋ฅ ํ ๊ฐ
- service_started : ๊ทธ ์๋น์ค๊ฐ ์์ํ ๋ค
- service_healthy : ๊ทธ ์๋น์ค์ ์ํ๊ฐ ์ ์์ผ ๋ ( healthcheck ์ต์ ์ ์ํด)
- service_completed_successfully : ๊ทธ ์๋น์ค๊ฐ ์ ์์ ์ผ๋ก ์ข ๋ฃ๋ ํ์
3. environment: ์ปจํ ์ด๋ ์์์ ์คํ๋ ๋ ํ๊ฒฝ๋ณ์๋ค์ ์ง์ ( ๋์ปคํ์ผ์ env)
4. networks : ํน์ ๋คํธ์ํฌ๋ก ๋ฌถ๊ณ ์ถ์ ๋ ์ง์ , ๋คํธ์ํฌ๋ service:์ ๊ฐ์ ๋จ์์ networks:๋ก ์ ์ธํ๋ค.
5. volumes: ๋์ปค ๋ณผ๋ฅจ ์ง์ , : ์ ๊ธฐ์ค์ผ๋ก ์ผ์ชฝ์ ์ด๋ฆ์, ์ค๋ฅธ์ชฝ์ ์ ์ฅํ๊ณ ์ถ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ค.
ex)
db:
enviroment:
POSTGRES_USER:"postgres"
POSTGRES_PASSWORD:"postgres"
volumes:
-"db-data:/var/lib/postgresql/data"
healthcheck:
test: /healthchecks/postgres.sh
interval: "5s"
networks:
- back-tier
์ฌ๋ฌ ์๋น์ค์์ ๊ณต์ ํ๋ ๊ณตํต ๊ตฌ์ฑ์ ๋ง๋ค ๋:
ex) airflow์ ๊ฒฝ์ฐ
x-airflow-common:
&airflow-common
image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.5.1}
environment:
&airflow-common-env
AIRFLOW__CORE__EXECUTOR: CeleryExecutor
…
_PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
volumes:
- ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
- ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
- ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
user: "${AIRFLOW_UID:-50000}:0"
depends_on:
&airflow-common-depends-on
redis:
condition: service_healthy
postgres:
condition: service_healthy
x-airflow-common : ์ฌ๋ฌ ์๋น์ค์์ ๊ณต์ ํ๋ ๊ณตํต ๊ตฌ์ฑ์ ์ ์ํ๋ค, ๋ณดํต anchor๋ผ๊ณ ๋ถ๋ฆ
&airflow-common :๋ณ์นญ ์ง์ , ๋ค๋ฅธ ์๋น์ค์์ airflow-common์ ๋ถ๋ฌ์ด์ผ๋ก์จ ๊ณตํต ๊ตฌ์ฑ์ ๊ฐ์ ธ์ฌ ์ ์์
ex)
airflow-scheduer:
<<: *airflow-common : airflwo-common