Day 49 Docker(4)

๐Ÿ“‹ย ๊ณต๋ถ€ ๋‚ด์šฉ

Docker Compose

์—ฌ๋Ÿฌ Container๋กœ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ตฌ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด์ด์ž ํ™˜๊ฒฝ์„ค์ •ํŒŒ์ผ
๊ฐœ๋ณ„ Container๋ฅผ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค ๋” ์ƒ์‚ฐ์„ฑ์ด ๋†’์Œ

docker-compose.yml or docker-compose.yaml

๋‹ค์–‘ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ dev, test, prod ๋“ฑ ์—ฌ๋Ÿฌ ๋ฒ„์ „์„ ๋งŒ๋“ค๊ธฐ๋„ ํ•จ

But, ๊ทธ๋งŒํผ ๋ฐฐ์›Œ์•ผ ํ•  ๊ฒƒ์ด ๋งŽ๊ณ  ๋ณต์žกํ•ด์ง

์‚ฌ์šฉ๋ฒ•

  • commands
1
2
3
4
5
6
7
8
docker-compose build
docker-compose up
docker-compose pull
docker-compose ps
docker-compose down
docker-compose start
docker-compose stop
docker-compose rm
  • version

docker-compose.y(a)ml

1. services

  • ํ”„๋กœ๊ทธ๋žจ์„ ๊ตฌ์„ฑํ•˜๋Š” ์„œ๋น„์Šค๋“ค

  • ๊ฐ๊ฐ Docker Image ์ง€์ •, Docker Container ์‹คํ–‰์œผ๋กœ ๊ตฌ์„ฑ๋จ
    (๊ฐ๊ฐ Dockerfile์„ ๊ฐ–๊ณ  ์žˆ๊ฑฐ๋‚˜ docker Hub์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œ๋ฐ›์•„์•ผ ํ•จ)

  • ์„œ๋น„์Šค๋ณ„๋กœ ํฌํŠธ๋ฒˆํ˜ธ, ํ™˜๊ฒฝ๋ณ€์ˆ˜, ๋””์Šคํฌ ๋ณผ๋ฅจ ๋“ฑ์„ ์ง€์ •

2. volumes

3. networks


๊ธฐ๋ณธ ์ด๋ฆ„์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ด๋ฆ„์˜ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด -f ์˜ต์…˜ ์‚ฌ์šฉ

1
docker-compose -f docker-compose.dev.yml up

์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ

docker-compose build

  • service๋“ค ์ค‘ build: {path} ๋กœ ์ง€์ •๋œ ๊ฒƒ์— ๋Œ€ํ•ด ๋นŒ๋“œ๊ฐ€ ์ง„ํ–‰๋จ

docker-compose pull

  • docker hub์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ฝ์–ด์˜ค๋ ค ํ•˜๋ฉฐ, image: {image_name}์œผ๋กœ ์ง€์ •๋จ

docker images

  • build ๋œ ์ด๋ฏธ์ง€๋“ค์€ ๊ฐœ๋ณ„ ์ด๋ฏธ์ง€ ์•ž์— ํด๋” ์ด๋ฆ„์ด prefix๋กœ ๋ถ™์Œ

docker-compose images

  • ์ปจํ…Œ์ด๋„ˆ์™€ ๊ทธ์— ์˜ํ•ด ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ด๋ฏธ์ง€๋“ค๋งŒ ๋ณด์—ฌ์คŒ

docker-compose push

  • docker hub ์œผ๋กœ ์ด๋ฏธ์ง€๋“ค์„ pushํ•˜๋ ค๊ณ  ํ•จ

์†Œํ”„ํŠธ์›จ์–ด ์‹œ์ž‘๊ณผ ์ค‘๋‹จ

docker-compose up

  • build(&pull) -> create -> start

docker-compose down

  • stop + remove (์ด๋ฏธ์ง€๋Š” ๋‚จ์•„์žˆ์Œ)

docker-compose stop

  • ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ค‘๋‹จ

docker-compose rm

  • ์ค‘๋‹จ์ƒํƒœ์ธ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์‚ญ์ œ

docker-compose ls

  • docker compose๋กœ ์‹คํ–‰์‹œํ‚จ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ๊ทธ๋ฃน์ง€์–ด์„œ ๋ณด์—ฌ์คŒ

docker-compose ps

  • docker compose๋กœ ์‹คํ–‰์‹œํ‚จ ์ปจํ…Œ์ด๋„ˆ๋“ค์˜ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ์คŒ

๋„คํŠธ์›Œํ‚น

docker๋ผ๋ฆฌ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

  • sevices์—์„œ ์ง€์ •ํ•œ ์ด๋ฆ„์œผ๋กœ host name ์ƒ์„ฑ
  • ๋‚ด๋ถ€์— DNS ์„œ๋ฒ„๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์ด๋ฆ„์„ ๋‚ด๋ถ€ IP๋กœ ๋ณ€ํ™˜

๋ณ„๋„ ๋„คํŠธ์›Œํฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ

  • networks ์— ๋„คํŠธ์›Œํฌ๋ฅผ ๋‚˜์—ดํ•˜๊ณ , ๊ฐ ๋„คํŠธ์›Œํฌ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ sevice์— ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•จ

docker network ls

docker compose ์‹ค์Šต

docker-compose.mac.yml

  • ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ด๋ฏธ์ง€๋Š” dockerhub์—์„œ ์ฝ์–ด์˜ค๋ฉฐ,
    ์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—” dockerfile์˜ ์œ„์น˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰
  • ๋„คํŠธ์›Œํฌ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
services:
  vote:
    build: ./vote # ์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์ด๋ฏ€๋กœ ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰
    # use python rather than gunicorn for local dev
    # ํด๋” ๋‚ด์˜ dockerfile์— ์ง€์ •๋œ command๋ฅผ overwriteํ•˜๋Š” ๊ฒƒ
    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 # ์ด๋ฏธ์ง€๋ฅผ docker hub์—์„œ ์ฝ์–ด์˜ด

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "postgres"

  • ํด๋ฆฐ์—… ํ›„ ์ƒˆ๋กœ ๋งŒ๋“  docker compose ํŒŒ์ผ์„ ํ™œ์šฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์‹คํ–‰ํ•ด๋ณด๊ธฐ
1
docker-compose -f docker-compose.mac.yml up

created docker images

Running docker containers

left: one vote for dog, righr: result of votes - 100% dogs

docker-compose.yml ๊ฐœ์„ ํ•˜๊ธฐ (1)

  • ๊ฐ service์— ์ ์ ˆํ•˜๊ฒŒ ๋„คํŠธ์›Œํฌ๋ฅผ ์ง€์ •ํ•ด์ค€๋‹ค. (๋ณด์•ˆ ๊ฐ•ํ™” ๋ชฉ์ )
  • ๋ฐ์ดํ„ฐ ๋ณด์กด์„ ์œ„ํ•ด postgresql db์— ๋ณผ๋ฅจ์„ ์ง€์ •ํ•ด์ค€๋‹ค.
code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
services:
  vote:
    ...
    networks:
      - back-tier
      - front-tier

  result:
    ...
    networks:
      - back-tier
      - front-tier

  worker:
    ...
    networks:
      - back-tier

  redis:
    ...
    networks:
      - back-tier

  db:
    ...
    networks:
      - back-tier
    volumes:
      - db-data:/var/lib/postgresql/data

networks:
  back-tier:
  front-tier:

volumes:
  db-data:

docker-compose.yml ๊ฐœ์„ ํ•˜๊ธฐ (2)

์ตœ์ข… ๊ฐœ์„ ๋œ .yml ํŒŒ์ผ

์„œ๋น„์Šค ๊ฐœ์„ 

  • depends_on : ์„œ๋น„์Šค๋“ค ๊ฐ„ ์˜์กด์„ฑ์ด ์žˆ์„ ๊ฒฝ์šฐ, ์‚ฌ์ „์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์„œ๋น„์Šค๋ฅผ ๊ธฐ์ˆ 
1
2
3
4
5
vote:
  depends_on:
    redis: #longform
      condition: service_healthy # service_started, service_completed_successfully
    - db # shortform
  • healthcheck : ํ•ด๋‹น ์„œ๋น„์Šค์˜ ๊ฑด๊ฐ• ์ƒํƒœ(์ž˜ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š”์ง€)๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ์ˆ 
    dockerfile์— ๊ธฐ์ˆ ๋œ ๋‚ด์šฉ์„ overwrite ํ•  ์ˆ˜ ์žˆ์Œ
    • return : service_started, service_healthy, service_completed_successfully
1
2
3
4
5
6
vote:
  healthcheck:
    test: ...
    interval: 15s
    timeout: 5s
    ...
  • volumes : ํ˜ธ์ŠคํŠธ์˜ ํด๋”์™€ container์˜ ํด๋”๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š”, mountํ•˜๋Š” ๊ธฐ๋Šฅ
1
2
3
4
5
6
7
vote:
  volumes:
    - ./vote:/app
db:
  volumes:
    - "db-data:/var/lib/postgresql/data" #named volume
    - "./healthchecks:/healthchecks" #host volume
  • environment : ์„œ๋น„์Šค๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์‹คํ–‰๋  ๋•Œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋“ค์„ ์ง€์ • (Dockerfile์˜ ENV)

    • map ๋ฌธ๋ฒ•
    1
    2
    3
    4
    
    environment:
      RACK_ENV: development
      SHOW: "true"
        USER_INPUT:
    
    • array ๋ฌธ๋ฒ•
    1
    2
    3
    4
    
    environment:
      - RACK_ENV=development
      - SHOW=true
        - USER_INPUT
    
  • build : context, dockerfile, args ๋“ฑ ๋นŒ๋“œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Œ

1
2
3
4
worker:
  build:
    context: ./worker
    ...

airflow์˜ docker-compose.yml ํŒŒ์ผ ๋ถ„์„

x-airflow-common

  • ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์—์„œ ๊ณต์œ ํ•˜๋Š” ๊ณตํ†ต ๊ตฌ์„ฑ์„ ์ •์˜
  • anchor(๋ณ„์นญ) - &airflow-common
    • ๋‚˜์ค‘์— YML ํŒŒ์ผ ๋ธ”๋ก์„ ๊ณ„์Šน ํ˜•ํƒœ๋กœ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์คŒ
    • ์žฌ์‚ฌ์šฉ ๋ฌธ๋ฒ•: <<: *airflow-common
  • version, services, volumes, networks๋ฅผ ์ œ์™ธํ•œ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์˜ ํ‚ค์›Œ๋“œ๋Š” ๋ชจ๋‘ anchor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
x-airflow-common:
  &airflow-common # ์•ต์ปค, ๋ณ„์นญ
  image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.5.1}
  # build: .
  environment:
    &airflow-common-env
    AIRFLOW__CORE__EXECUTOR: CeleryExecutor
    ...
    _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
  volumes:  # ๋ชจ๋“  container๋“ค์€ ์ด ์„ธ๊ฐœ์˜ volume์„ ๊ณต์œ ํ•จ, host 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

services

  • postgres
  • redis
  • airflow-webserver
  • airflow-scheduler
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  ...
  airflow-scheduler:
    <<: *airflow-common # ์œ„์—์„œ ์–ธ๊ธ‰๋˜์—ˆ๋˜ ๋ณ„์นญ์„ ์‚ฌ์šฉ
    command: scheduler
    healthcheck:
      test: ["CMD-SHELL", 'airflow jobs check --job-type SchedulerJob --hostname "$${HOSTNAME}"']
      interval: 10s
      timeout: 10s
      retries: 5
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully
  • airflow-worker
  • airflow-triggerer
  • airflow-init

ํŒŒ์ด์ฌ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•˜๋Š” ๊ฒฝ์šฐ

  • ๋งค๋ฒˆ container์— ์ ‘์†ํ•ด ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๊ณ , ๋ณด์กด๋˜์ง€ ์•Š์•„ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ BAD
  • docker-compose.yml์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉ
1
2
- _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
+ _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:- yfinance pandas numpy}

โ— ๋Š๋‚€ ์ 

docker compose์™€ ๊ทธ ์‚ฌ์šฉ๋ฐฉ๋ฒ•, .yml ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑ๋ฒ• ๋“ฑ์„ ๋ฐฐ์šฐ๋ฉด์„œ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ€์ง„ ํ”„๋กœ๊ทธ๋žจ์„ ๋„์ปค๋กœ ๋ฐ›๊ณ  ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •์— ๋Œ€ํ•ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๊ฐ•์˜ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜๋ฉด์„œ, ๋„์ปค, ์ปจํ…Œ์ด๋„ˆ, ์ด๋ฏธ์ง€, ๋„์ปค ์ปดํฌ์ฆˆ ๋“ฑ ๊ฐœ๋…์— ๋Œ€ํ•ด ํ•œ๋ฒˆ ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ์ฃผ๋ง์ด๋‚˜ ๋‹ค์Œ์ฃผ ๋ฐฉํ•™ ๋™์•ˆ ๊ณต๋ถ€ํ•˜๊ณ  ์ •๋ฆฌํ•ด์„œ ๋ธ”๋กœ๊ทธ์— ์˜ฌ๋ ค์•ผ๊ฒ ๋‹ค.

๋ฐฉํ•™๋™์•ˆ ์ด์ „ ์ˆ˜์—…์„ ๋ณต์Šตํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์Šฌ์Šฌ CS ๊ณต๋ถ€๋„ ์‹œ๊ฐ„ ์ •ํ•ด์„œ ์‹œ์ž‘ํ•ด์•ผ๊ฒ ๋‹ค. ๋ญ”์ง€ ์•Œ์ง€๋งŒ, ๋“ค์œผ๋ฉด ๊ธฐ์–ต๋„ ๋‚˜์ง€๋งŒ ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…์„ ๋ชปํ•˜๋Š” ๊ฐœ๋…์ด ์ ์  ๋Š˜์–ด๋‚˜๊ณ  ์žˆ์–ด์„œ ๋‹ต๋‹ตํ•˜๊ณ  ๋ถˆ์•ˆํ•˜๋‹ค.

Hugo๋กœ ๋งŒ๋“ฆ
Jimmy์˜ Stack ํ…Œ๋งˆ ์‚ฌ์šฉ ์ค‘