๐Ÿฅž BE
home

Docker Compose

Docker Compose๋ž€?

Docker Compose๋ž€ ๋‹จ์ผ ์„œ๋ฒ„์—์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์˜ ์„œ๋น„์Šค๋กœ ์ •์˜ํ•ด ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฌถ์Œ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๊ด€๋ฆฌ ๋„๊ตฌ์ด๋‹ค.
Docker Compose์—์„œ๋Š” compose ํŒŒ์ผ์„ ์ค€๋น„ํ•ด์„œ ์ปค๋งจ๋“œ๋ฅผ 1ํšŒ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ทธ ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ์„ค์ •์„ ์ฝ์–ด๋“ค์—ฌ ๋ชจ๋“  ์ปจํ…Œ์ด๋„ˆ ์„œ๋น„์Šค๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

Docker Compose๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•˜๋‚˜์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋™์ž‘ํ•  ๋•Œย Docker Compose๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ด๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์”ฉ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค๋ฉด, ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ์›น ์„œ๋ฒ„ ์ปจํ…Œ์ด๋„ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปจํ…Œ์ด๋„ˆ ๋‘ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ๊ฐ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
$ docker run --name wordpress_db -d mysql:8 $ docker run -d -p 8080:80 \ --link wordpress_db:mysql --name seunghwan_wordpress \ wordpress:latest
Shell
๋ณต์‚ฌ
์œ„์˜ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด wordpress์™€ mysql ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
์ด์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋กœ ๊ตฌ์„ฑ๋œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•ด run ๋ช…๋ น์–ด๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋‹จ๊ณ„์—์„œ๋Š” ์ด๋Ÿฐ์‹์œผ๋กœ ์ผ์ผํžˆ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ๋Š” ๋ฒˆ๊ฑฐ๋กญ๋‹ค.
๋งค๋ฒˆ run ๋ช…๋ น์–ด์— ์˜ต์…˜์„ ์„ค์ •ํ•ด CLI๋กœ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์˜ ์„œ๋น„์Šค๋กœ ์ •๋ฆฌํ•ด ์ปจํ…Œ์ด๋„ˆ ๋ฌถ์Œ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข€ ๋” ํŽธ๋ฆฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๋ฅผ ์œ„ํ•ด ๋„์ปค ์ปดํฌ์ฆˆ(Docker Compose)๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ด์šฉํ•œ ์„œ๋น„์Šค์˜ ๊ฐœ๋ฐœ๊ณผ CI๋ฅผ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ๋กœ์„œ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•œ๋‹ค.

Docker Compose์˜ ๊ตฌ์กฐ

Docker Compose๋Š” ์‹œ์Šคํ…œ ๊ตฌ์ถ•์— ํ•„์š”ํ•œ ์„ค์ •์„ YAML ํฌ๋งท์œผ๋กœ ๊ธฐ์žฌํ•œ ์ •์˜ ํŒŒ์ผ์„ ์ด์šฉํ•ด ์ „์ฒด ์‹œ์Šคํ…œ์„ ์ผ๊ด„ ์‹คํ–‰(run) ๋˜๋Š” ์ผ๊ด„ ์ข…๋ฃŒ ๋ฐ ์‚ญ์ œ(down) ํ•  ์ˆ˜ ์žˆ๋‹ค.
YAML ํŒŒ์ผ์—๋Š” ์ปจํ…Œ์ด๋„ˆ๋‚˜ ๋ณผ๋ฅจ์„ โ€˜์–ด๋– ํ•œ ์„ค์ •์œผ๋กœ ๋งŒ๋“ค์ง€โ€™์— ๋Œ€ํ•œ ํ•ญ๋ชฉ์ด ๊ธฐ์žฌ๋˜์–ด ์žˆ๋‹ค.
up ์ปค๋งจ๋“œ
โ€ข
docker run ์ปค๋งจ๋“œ์™€ ๋น„์Šท
โ€ข
์ •์˜ ํŒŒ์ผ์— ๊ธฐ์žฌ๋œ ๋‚ด์šฉ๋Œ€๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋‚ด๋ ค๋ฐ›๊ณ  ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰
โ€ข
์ •์˜ ํŒŒ์ผ์—๋Š” ๋„คํŠธ์›Œํฌ๋‚˜ ๋ณผ๋ฅจ์— ๋Œ€ํ•œ ์ •์˜๋„ ๊ธฐ์žฌํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ฃผ๋ณ€ ํ™˜๊ฒฝ์„ ํ•œ๊บผ๋ฒˆ์— ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Œ
down ์ปค๋งจ๋“œ
โ€ข
์ปจํ…Œ์ด๋„ˆ์™€ ๋„คํŠธ์›Œํฌ๋ฅผ ์ •์ง€ ๋ฐ ์‚ญ์ œ
โ€ข
๋ณผ๋ฅจ๊ณผ ์ด๋ฏธ์ง€๋Š” ์‚ญ์ œ
โ€ข
์ปจํ…Œ์ด๋„ˆ์™€ ๋„คํŠธ์›Œํฌ ์‚ญ์ œ ์—†์ด ์ข…๋ฃŒ๋งŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด stop ์ปค๋งจ๋“œ๋ฅผ ์‚ฌ์šฉ
์ด์™ธ์—๋„ ๊ฐ ์ปจํ…Œ์ด๋„ˆ์˜ ์˜์กด์„ฑ, ๋„คํŠธ์›Œํฌ, ๋ณผ๋ฅจ ๋“ฑ์„ ํ•จ๊ป˜ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

YAML

โ€ข
๋‹ค์ˆ˜์˜ Container๋กœ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ตฌ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํˆด + ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ(yml or yaml)
โ—ฆ
docker-compose.yml๋กœ ์„ค์ •
โ—ฆ
์—ฌ๊ธฐ์„œ ๋‹ค์–‘ํ•œ ํ…Œ์ŠคํŠธ๋“ค๋„ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ
โ—ฆ
๋‹ค์–‘ํ•œ ๋ฒ„์ „์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ ์ผ๋ฐ˜์  (dev, test, prod ๋“ฑ๋“ฑ)
โ–ช
ex) docker-compose.dev.yml
โ€ข
๊ฐœ๋ณ„ Container๋ฅผ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋” ์ƒ์‚ฐ์„ฑ์ด ๋†’์Œ
โ€ข
์‚ฌ์šฉ๋ฒ• ์ž์ฒด๋Š” ๊ฐ„๋‹จ : ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“  ์ปจํ…Œ์ด๋„ˆ์—๊ฒŒ ์ ์šฉ๋จ
$ docker-compose build $ docker-compose up # -> pull + build + run $ docker-compose pull $ docker-compose ps $ docker-compose down $ docker-compose start $ docker-compose stop $ docker-compose rm
Shell
๋ณต์‚ฌ

docker-compose.yml ์ž‘์„ฑ ๋ฐ ํ™œ์šฉ

Wordpress ์‚ฌ์ดํŠธ

์›Œ๋“œํ”„๋ ˆ์Šค๋Š” ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋กœ, ์„œ๋ฒ„์— ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
์›Œ๋“œํ”„๋ ˆ์Šค ์ปจํ…Œ์ด๋„ˆ์™€ MySQL ์ปจํ…Œ์ด๋„ˆ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ์›Œ๋“œํ”„๋ ˆ์Šค๋Š” ๊ฐ„๋‹จํžˆ ๋งํ•ด ๋ธ”๋กœ๊ทธ ์ƒ์„ฑ ๋„๊ตฌ์™€ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ, ์›น ์‚ฌ์ดํŠธ ์ž‘์„ฑ์ž๊ฐ€ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ณ , ์›น ์‚ฌ์ดํŠธ ์—ด๋žŒ์ž์˜ ์š”์ฒญ์— ๋”ฐ๋ผ ์›น ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. ์ฆ‰, ํ”„๋กœ๊ทธ๋žจ์ด MySQL์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

MySQL, Wordpress ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ ์‹œ ํ•„์š”ํ•œ ์˜ต์…˜๊ณผ ์ธ์ž

โ€ข
MySQL
docker run --name ์ปจํ…Œ์ด๋„ˆ_์ด๋ฆ„ -dit --net=๋„คํŠธ์›Œํฌ_์ด๋ฆ„ -e MYSQL_ROOT_PASSWORD=MySQL_๋ฃจํŠธ_ํŒจ์Šค์›Œ๋“œ -e MYSQL_DATABASE=๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค_์ด๋ฆ„ -e MYSQL_USER=MySQL_์‚ฌ์šฉ์ž์ด๋ฆ„ -e MYSQL_PASSWORD=MySQL_ํŒจ์Šค์›Œ๋“œ mysql --character-set-server=๋ฌธ์ž_์ธ์ฝ”๋”ฉ --collation-server=์ •๋ ฌ_์ˆœ์„œ --default-authentication-plugin=์ธ์ฆ_๋ฐฉ์‹
Shell
๋ณต์‚ฌ
โ€ข
Wordpress
docker run --name ์ปจํ…Œ์ด๋„ˆ_์ด๋ฆ„ -dit --net=๋„คํŠธ์›Œํฌ_์ด๋ฆ„ -p ํฌํŠธ_์„ค์ • -e WORDPRESS_DB_HOST=๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค_์ปจํ…Œ์ด๋„ˆ_์ด๋ฆ„ -e WORDPRESS_DB_NAME=๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค_์ด๋ฆ„ -e WORDPRESS_DB_USER=๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค_์‚ฌ์šฉ์ž์ด๋ฆ„ -e WORDPRESS_DB_PASSWORD=๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค_ํŒจ์Šค์›Œ๋“œ wordpress
Shell
๋ณต์‚ฌ

docker run ๋ช…๋ น์–ด๋กœ ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ

docker run -d --name wordpress_db \ --network geonoo_network \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=y3787 \ -e MYSQL_DATABASE=y3787 \ -e MYSQL_USER=y3787 \ -e MYSQL_PASSWORD=y3787 \ -v mysql:/var/lib/mysql \ --restart unless-stopped \ mysql:8
Shell
๋ณต์‚ฌ
docker run -d --name geonoo_wordpress \ --network geonoo_network \ -p 8080:80 \ --link wordpress_db:mysql \ -e WORDPRESS_DB_HOST=db:3306 \ -e WORDPRESS_DB_NAME=y3787 \ -e WORDPRESS_DB_USER=y3787 \ -e WORDPRESS_DB_PASSWORD=y3787 \ --restart unless-stopped \ wordpress:latest
Shell
๋ณต์‚ฌ

yaml ํŒŒ์ผ๋กœ ๋ณ€๊ฒฝ

version: '3.9' services: db: image: mysql:8 volumes: - db:/var/lib/mysql restart: unless-stopped environment: - MYSQL_ROOT_PASSWORD=seosh817 - MYSQL_DATABASE=seosh817 - MYSQL_USER=seosh817 - MYSQL_PASSWORD=seosh817 networks: - wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" restart: unless-stopped environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: seosh817 WORDPRESS_DB_PASSWORD: seosh817 WORDPRESS_DB_NAME: seosh817 networks: - wordpress volumes: db: {} networks: wordpress: {}
YAML
๋ณต์‚ฌ
์œ„์˜ docker-compose.yml ํŒŒ์ผ์„ ๋ณด๋ฉด ์„œ๋น„์Šค๋กœ db, wordpress ๋‘๊ฐœ๊ฐ€ ์กด์žฌํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ณผ๋ฅจ์œผ๋กœ db, ๋„คํŠธ์›Œํฌ๋กœ wordpress๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„œ๋น„์Šค์—์„œ ํ•ด๋‹น ๋ณผ๋ฅจ๊ณผ ๋„คํŠธ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ๋‹ค.
์–ด๋– ํ•œ ์„ค์ •๋„ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋„์ปค ์ปดํฌ์ฆˆ๋Š” ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ์˜ docker-compose.yml ํŒŒ์ผ์„ ์ฝ์–ด ๋กœ์ปฌ์˜ ๋„์ปค ์—”์ง„์—๊ฒŒ ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ์„ ์š”์ฒญํ•œ๋‹ค. docker compse up ๋ช…๋ น์–ด๋กœ ๋„์ปค ์ปดํฌ์ฆˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
docker-compose up -d
YAML
๋ณต์‚ฌ
์ปดํฌ์ฆˆ ํŒŒ์ผ(YAML ํ˜•์‹)์˜ ์ž‘์„ฑ ์š”๋ น - ์ฒซ ์ค„์— ๋„์ปค ์ปดํฌ์ฆˆ ๋ฒ„์ „์„ ๊ธฐ์žฌ - ์ฃผ ํ•ญ๋ชฉ services, networks, volumes ์•„๋ž˜์— ์„ค์ • ๋‚ด์šฉ์„ ๊ธฐ์žฌ - ํ•ญ๋ชฉ ๊ฐ„์˜ ์ƒํ•˜ ๊ด€๊ณ„๋Š” ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•œ ๋“ค์—ฌ์“ฐ๊ธฐ๋กœ ๋‚˜ํƒ€๋‚ธ๋‹ค. - ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” ๊ฐ™์€ ์ˆ˜์˜ ๋ฐฐ์ˆ˜๋งŒํผ์˜ ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•œ๋‹ค. - ์ด๋ฆ„์€ ์ฃผ ํ•ญ๋ชฉ ์•„๋ž˜์— ๋“ค์—ฌ์“ฐ๊ธฐํ•œ ๋‹ค์Œ ๊ธฐ์žฌํ•œ๋‹ค. - ์ปจํ…Œ์ด๋„ˆ ์„ค์ • ๋‚ด์šฉ์€ ์ด๋ฆ„ ์•„๋ž˜์— ๋“ค์—ฌ์“ฐ๊ธฐํ•œ ๋‹ค์Œ ๊ธฐ์žฌํ•œ๋‹ค. - ์—ฌ๋Ÿฌ ํ•ญ๋ชฉ์„ ๊ธฐ์žฌํ•˜๋ ค๋ฉด ์ค„ ์•ž์— โ€˜-โ€™์„ ๋ถ™์ธ๋‹ค. - ์ด๋ฆ„ ๋’ค์—๋Š” ์ฝœ๋ก (:)์„ ๋ถ™์ธ๋‹ค. - ์ฝœ๋ก  ๋’ค์—๋Š” ๋ฐ˜๋“œ์‹œ ๊ณต๋ฐฑ์ด ์™€์•ผ ํ•œ๋‹ค.(๋ฐ”๋กœ ์ค„๋ฐ”๊ฟˆํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์˜ˆ์™ธ) - # ๋’ค์˜ ๋‚ด์šฉ์€ ์ฃผ์„์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค. - ๋ฌธ์ž์—ด์€ ์ž‘์€๋”ฐ์˜ดํ‘œ(โ€™) ๋˜๋Š” ํฐ๋”ฐ์˜ดํ‘œ(โ€)๋กœ ๊ฐ์‹ธ ์ž‘์„ฑํ•œ๋‹ค.

์ปดํฌ์ฆˆ ํŒŒ์ผ์˜ ํ•ญ๋ชฉ

โ€ข
์ฃผ ํ•ญ๋ชฉ
ํ•ญ๋ชฉ
๋‚ด์šฉ
services
์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ •์˜ํ•œ๋‹ค.
networks
๋„คํŠธ์›Œํฌ๋ฅผ ์ •์˜ํ•œ๋‹ค.
volumes
๋ณผ๋ฅจ์„ ์ •์˜ํ•œ๋‹ค.
โ€ข
์ž์ฃผ ๋‚˜์˜ค๋Š” ์ •์˜ ๋‚ด์šฉ
ํ•ญ๋ชฉ
docker run ์ปค๋งจ๋“œ์˜ ํ•ด๋‹น ์˜ต์…˜ ๋˜๋Š” ์ธ์ž
๋‚ด์šฉ
images
์ด๋ฏธ์ง€ ์ธ์ž
์‚ฌ์šฉํ•  ์ด๋ฏธ์ง€๋ฅผ ์ง€์ •
networks
โ€”net
์ ‘์†ํ•  ๋„คํŠธ์›Œํฌ๋ฅผ ์ง€์ •
volumes
-v, โ€”mount
์Šคํ† ๋ฆฌ์ง€ ๋งˆ์šดํŠธ๋ฅผ ์„ค์ •
ports
-p
ํฌํŠธ ์„ค์ •
environment
-e
ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •
depends_on
์—†์Œ
๋‹ค๋ฅธ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์˜์กด๊ด€๊ณ„๋ฅผ ์ •์˜
restart
์—†์Œ
์ปจํ…Œ์ด๋„ˆ ์ข…๋ฃŒ ์‹œ ์žฌ์‹œ์ž‘ ์—ฌ๋ถ€๋ฅผ ์„ค์ •

example-voting-app

Docker์—์„œ ๊ณต์‹์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ์˜ˆ์ œ ์ƒ˜ํ”Œ

example-voting-app
dockersamples
โ€ข
์•„ํ‚คํ…์ฒ˜ ์„ค๋ช…
โ—ฆ
๋‘ ์˜ต์…˜ ์‚ฌ์ด์—์„œ ํˆฌํ‘œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” Python ํ”„๋ก ํŠธ์—”๋“œ ์›น ์•ฑ
โ—ฆ
์ƒˆ๋กœ์šด ํˆฌํ‘œ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š”ย Redis
โ—ฆ
ํˆฌํ‘œ๋ฅผ Consumeํ•˜๊ณ  ๋„ํŠธ๋„ท(.NET) ์›Œ์ปค์—์„œ ์ €์žฅํ•˜๋Š”ย .NETย Worker
โ—ฆ
๋„์ปค ๋ณผ๋ฅจ์— ์˜ํ•ด ์ง€์›๋˜๋Š”ย Postgresย ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
โ—ฆ
์‹ค์‹œ๊ฐ„์œผ๋กœ ํˆฌํ‘œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š”ย Node.jsย ์›น ์•ฑ
git clone https://github.com/Y-gw/example-voting-app.git
๋จผ์ € ๊ธฐ์กด ๋ฐฉ์‹๋Œ€๋กœ ๋งค๋‰ด์–ผํ•˜๊ฒŒ ํ•˜๋‚˜์”ฉ ๋นŒ๋“œํ•ด๋ณด์ž.
โ€ข
์ด๋ฏธ์ง€ ๋นŒ๋“œ
$ docker build -t vote ./vote $ docker build -t result ./result $ docker build -t worker ./worker
Shell
๋ณต์‚ฌ
โ€ข
์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰
# detached ๋ชจ๋“œ๋กœ ์œ„์˜ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์‹คํ–‰ $ docker run -d --name=redis redis $ docker run -d -e POSTGRES_PASSWORD=postgres --name=db postgres $ docker run -d --name=vote -p 5001:80 vote $ docker run -d --name=result -p 5002:80 result $ docker run -d --name=worker worker
Shell
๋ณต์‚ฌ
โ€ข
network ํ†ต์‹  ํ™•์ธ
## vote(python app) container๋กœ ๋“ค์–ด๊ฐ€์„œ redis์™€์˜ ํ†ต์‹ ์„ ping์„ ํ†ตํ•ด ํ™•์ธ $ docker exec -it --user root vote sh $ apt-get update && apt update $ apt install -y iputils-ping $ ping redis >> ping: cannot resolve redis: Unknown host
Shell
๋ณต์‚ฌ
โ€ข
docker images
โ—ฆ
redis์™€ postgres๋Š” ๊ณต์‹ ์ด๋ฏธ์ง€๋“ค์ด๋ผ ๋นŒ๋“œํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
โ€ข
์œ„์™€ ๊ฐ™์ด ์ด๋ ‡๊ฒŒ ๋‚ด๊ฐ€ ์ผ์ผํžˆ ํ•˜๋‚˜์”ฉ ์‹คํ–‰ํ•˜๋ฉด ๋™์ž‘ํ• ๊นŒ?
โ—ฆ
๊ฐ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„์˜ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ์•ˆ๋˜๊ณ  ์žˆ์Œ!
โ—ฆ
์ปจํ…Œ์ด๋„ˆ ๊ฐ„ ํ†ต์‹ ์ด ์•ˆ๋˜๊ณ  ์žˆ์Œ์„ ping์„ ํ†ตํ•ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค
โ€ข
๋„คํŠธ์›Œํฌ issue ์„ธ๋ถ€ ์ •๋ณด
โ—ฆ
python app์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด redis๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
โ—ฆ
vote/app.py
def get_redis(): """ Redis ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ด ํ•จ์ˆ˜๋Š” Flask์˜ g ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Redis ์ธ์Šคํ„ด์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œ ๋ฒˆ์˜ ์š”์ฒญ์— ๋Œ€ํ•ด ๋™์ผํ•œ Redis ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•œ๋‹ค. Returns: Redis: Redis - ํด๋ผ์ด์–ธํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. Raises: ConnectionError: Redis - ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ๋ฐœ์ƒํ•œ๋‹ค. TimeoutError: Redis - ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์ด ์‹œ๊ฐ„ ์ดˆ๊ณผ๋˜๋Š” ๊ฒฝ์šฐ ๋ฐœ์ƒํ•œ๋‹ค. """ if not hasattr(g, 'redis'): # g ๊ฐ์ฒด์— Redis ์ธ์Šคํ„ด์Šค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ Redis ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. # host๋Š” "redis"๋กœ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉฐ, db๋Š” 0์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค. # socket_timeout์€ ์—ฐ๊ฒฐ ์‹œ๋„ ์‹œ๊ฐ„์„ 5์ดˆ๋กœ ์„ค์ •ํ•œ๋‹ค. g.redis = Redis(host="redis", db=0, socket_timeout=5) return g.redis
Python
๋ณต์‚ฌ
โ—ฆ
result/server.js
var pool = new pg.Pool({ connectionString: 'postgres://postgres:postgres@db/postgres' });
JavaScript
๋ณต์‚ฌ
postgres ์—ฐ๊ฒฐ์‹œ postgres:postgres๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ์„ ์ฃผ์˜๊นŠ๊ฒŒ ๋ณผ ๊ฒƒ!
@ ๋‹ค์Œ์— ์˜ค๋Š” ์ด๋ฆ„์€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฆ„
โ†’ Docker Compose ํŒŒ์ผ์—์„œ db๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ PostgreSQL ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ •์˜
โ—ฆ
worker/Program.cs
var pgsql = OpenDbConnection("Server=db;Username=postgres;Password=postgres;"); var redisConn = OpenRedisConnection("redis");
C#
๋ณต์‚ฌ
worker์—์„œ๋Š” postgresql๊ณผ redis๋ฅผ ๋™์‹œ์— ํ†ต์‹ 
์ด ๋ถ€๋ถ„์—์„œ ์„œ๋กœ์˜ ์กด์žฌ๋ฅผ ๋ชฐ๋ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ โ†’ ํ†ต์‹  X

๋„คํŠธ์›Œํฌ issue ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

โ€ข
docker์˜ network ๊ธฐ๋Šฅ ์‚ฌ์šฉ
โ—ฆ
์ „์—๋Š” docker run์˜ link ์˜ต์…˜์„ ์‚ฌ์šฉ
โ€ข
network๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ  ๋ชจ๋“  ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์ด ๋„คํŠธ์›Œํฌ ์•ˆ์œผ๋กœ ์ง€์ •
โ—ฆ
์—ฐ๊ฒฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ณ„๊ฐœ์˜ ๋„คํŠธ์›Œํฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉ๋„ ๊ฐ€๋Šฅํ•จ
โ–ช
์•„๋ž˜์—์„œ๋Š” 2๊ฐ€์ง€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ๋“ค ๊ฐ„ ํ†ต์‹  ๊ทธ๋ฃน์„ ๋งŒ๋“ค ์˜ˆ์ •
โ–ช
back-tier
โ–ช
front-tier
โ—ฆ
๋งค๋‰ด์–ผ ์˜ˆ์ œ์—์„œ๋Š” mynetwork ๋ผ๋Š” ๋„คํŠธ์›Œํฌ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ  ์ง„ํ–‰ ์˜ˆ์ •

docker network create

๋‹ค์‹œ ์ „์ฒด ๊ณผ์ •์„ ์‹คํ–‰ํ•ด๋ณด์ž.
โ€ข
์ด๋ฏธ์ง€ ๋นŒ๋“œ
$ docker build -t vote ./vote $ docker build -t result ./result $ docker build -t worker ./worker
Shell
๋ณต์‚ฌ
โ€ข
์ปจํ…Œ์ด๋„ˆ ์ •๋ฆฌ
# ๋งŒ์•ฝ ์ค‘์š”ํ•œ ๊ฒƒ์ด ์—†๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜ํ–‰ $ docker container rm -f $(docker container ls -aq) # ์ค‘์š”ํ•œ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ $ docker ps $ docker stop {์ปจํ…Œ์ด๋„ˆ id} $ docker rm {์ปจํ…Œ์ด๋„ˆ id}
Shell
๋ณต์‚ฌ
โ€ข
๋„คํŠธ์›Œํฌ ์ƒ์„ฑ
$ docker network create mynetwork
Shell
๋ณต์‚ฌ
โ€ข
์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ (--network ํƒœ๊ทธ ์ง€์ •)
$ docker run -d --name=redis --network mynetwork redis # password ์„ค์ •๊ณผ ํ•จ๊ป˜ docker run $ docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres $ 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
Shell
๋ณต์‚ฌ
โ€ข
redis์™€ ํ†ต์‹  ํ™•์ธ
$ docker exec -it --user root vote sh $ apt-get update && apt update && apt install -y iputils-ping $ apt install -y iputils-ping $ ping redis # ping redis -> ์•„๋ž˜์™€ ๊ฐ™์ด ํ†ต์‹ ์ด ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธ ๊ฐ€๋Šฅ! PING redis (172.22.0.2) 56(84) bytes of data. 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=1 ttl=64 time=0.934 ms 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=2 ttl=64 time=0.099 ms 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=3 ttl=64 time=0.135 ms 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=4 ttl=64 time=0.079 ms 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=5 ttl=64 time=0.252 ms 64 bytes from redis.mynetwork (172.22.0.2): icmp_seq=6 ttl=64 time=0.235 ms
Shell
๋ณต์‚ฌ

Docker compose๋ฅผ ํ†ตํ•œ ์‹คํ–‰

์•ž์„œ 5๊ฐœ์˜ Container๋ฅผ ์ผ์ผํžˆ ์‹คํ–‰ํ–ˆ์„ ๋•Œ์˜ ๋ฌธ์ œ์ 
โ€ข
Postgres๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ถ€๋ถ„์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Œ
# $ ping db PING db (192.168.107.3) 56(84) bytes of data. 64 bytes from db.mynetwork (192.168.107.3): icmp_seq=1 ttl=64 time=0.183 ms 64 bytes from db.mynetwork (192.168.107.3): icmp_seq=2 ttl=64 time=0.048 ms 64 bytes from db.mynetwork (192.168.107.3): icmp_seq=3 ttl=64 time=0.055 ms # ์‘? ํ†ต์‹ ์€ ๋˜๋Š”๋ฐ..?
Shell
๋ณต์‚ฌ
โ—ฆ
์ด๋Š” Postgres ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์ ์ ˆํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•„ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ.
โ—ฆ
Worker ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ OpenDbConnection ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, Postgres ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ ์ •๋ณด๊ฐ€ ์ž˜๋ชป ์„ค์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Œ.
โ—ฆ
docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres
โ—ฆ
worker/Program.cs
var pgsql = OpenDbConnection("Server=db;Username=postgres;Password=postgres;"); var redisConn = OpenRedisConnection("redis");
C#
๋ณต์‚ฌ
โ€ข
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Container๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์•„๋ž˜ 2๊ฐœ์˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•จ
โ—ฆ
POSTGRES_USER: "postgres"
โ—ฆ
POSTGRES_PASSWORD: "postgres"
โ†’ ์ด๊ฑธ docker-compose ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ์„ ํ†ตํ•ด ๋„˜๊ธฐ๋ฉด์„œ ํ•ด๊ฒฐํ•ด๋ณผ ์˜ˆ์ •

docker-compose.yml๋กœ ํฌํŒ…

โ€ข
์•ž์„œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์”ฉ ์‹คํ–‰ํ•  ๋•Œ ๋„คํŠธ์›Œํ‚น ๋ถ€๋ถ„์€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Œ.
โ€ข
docker volume์ด๋ž€?
โ—ฆ
Docker volume์€ Docker ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•.
โ—ฆ
์ปจํ…Œ์ด๋„ˆ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋…๋ฆฝ์ ์ธ ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‚ญ์ œ๋˜๋ฉด ๊ทธ ์•ˆ์˜ ๋ฐ์ดํ„ฐ๋„ ํ•จ๊ป˜ ์‚ญ์ œ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Docker volume์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ŠคํŠธ ๋จธ์‹ ์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์— ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
services ํ‚ค ๋ณด๊ธฐ
โ€ข
docker-compose.mac.yml
# v2 and v3 are now combined! # docker-compose v1.27+ required # % docker-compose version # Docker Compose version v2.15.1 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"
YAML
๋ณต์‚ฌ
โ€ข
Demo
## ๋จผ์ € ์ฒญ์†Œ ํ•œ ๋ฒˆ ํ•˜๊ธฐ $ docker container rm -f $(docker container ls -aq) # docker image rm -f $(docker image ls -q) ## ํ™•์ธํ•ด๋ณด๊ธฐ $ docker ps -a $ docker images ## ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ์•ž์˜ docker-compose.mac.yml์˜ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์‹คํ–‰ํ•ด๋ณด๊ธฐ $ docker-compose -f docker-compose.mac.yml build $ docker-compose -f docker-compose.mac.yml up -d ## db ์ปจํ…Œ์ด๋„ˆ ์ ‘์† docker exec -it --user=postgres example-voting-app-db-1 sh / $ whoami postgres / $ psql psql (15.4) Type "help" for help. ## \c: Connect to database postgres=# \c You are now connected to database "postgres" as user "postgres". ## \dt: List tables postgres=# \dt List of relations Schema | Name | Type | Owner --------+-------+-------+---------- public | votes | table | postgres (1 row) postgres=# select * from votes; id | vote -----------------+------ cb9d5ad7206be28 | a (1 row) exit $ docker-compose -f docker-compose.mac.yml down >> โœ” Container example-voting-app-worker-1 Removed 0.6s โœ” Container example-voting-app-db-1 Removed 0.8s โœ” Container example-voting-app-vote-1 Removed 1.0s โœ” Container example-voting-app-result-1 Removed 0.7s โœ” Container example-voting-app-redis-1 Removed 0.9s โœ” Network example-voting-app_default Removed
Shell
๋ณต์‚ฌ

๋„คํŠธ์›Œํฌ ์ •์˜๋ฅผ ํ†ตํ•œ docker-compose ๊ฐœ์„ 

โ€ข
๋ชจ๋“  ๋„คํŠธ์›Œํฌ๋ฅผ ๋‹ค ํ†ต์ผ ์‹œํ‚ค๋Š” ๊ฒƒ์€ ๋ฐ”๋žŒ์ง ํ•˜์ง€ ์•Š๋‹ค.
โ—ฆ
๋„คํŠธ์›Œํฌ๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„๋ฆฌ์‹œ์ผœ์ฃผ๋Š” ๊ฒƒ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ์„ฑ, ํ™•์žฅ์„ฑ, ์œ ์—ฐ์„ฑ ๋ฐ ์„œ๋น„์Šค ๋ถ„๋ฆฌ ์ธก๋ฉด์—์„œ ๋” ๋ฐ”๋žŒ์ง
โ—ฆ
์˜ˆ์‹œ : ๋ฐฑ์—”๋“œ ๋‚ด ์•ž ๋กœ์ง, ๋ฐฑ ๋กœ์ง
โ€ข
docker-compose.yml๋กœ ํฌํŒ…: networks ์ •์˜
โ—ฆ
front tier : ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœ
โ—ฆ
back tier : ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœX
โ—ฆ
์ด๋ฅผ ํ†ตํ•œ network isolation. ํ˜น์‹œ๋ผ๋„ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ ์ฐจ๋‹จ
1.
๊ฒฉ๋ฆฌ(Isolation): ๊ฐ ์„œ๋น„์Šค๋ฅผ ๋„คํŠธ์›Œํฌ๋กœ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ, ์„œ๋กœ ๋‹ค๋ฅธ ์„œ๋น„์Šค ๊ฐ„์˜ ๋„คํŠธ์›Œํฌ ๊ฒฉ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ์„œ๋น„์Šค์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ , ํ•œ ์„œ๋น„์Šค์˜ ์žฅ์• ๋‚˜ ๊ณผ๋ถ€ํ•˜๊ฐ€ ๋‹ค๋ฅธ ์„œ๋น„์Šค์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
2.
์„ธ๋ถ„ํ™”(Segmentation): ๋„คํŠธ์›Œํฌ๋ฅผ back-tier์™€ front-tier๋กœ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ, ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค์™€ ํ”„๋ก ํŠธ์—”๋“œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋Š” ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ(back-tier)์— ์†ํ•˜๊ณ , ํ”„๋ก ํŠธ์—”๋“œ ์„œ๋น„์Šค๋Š” ๋‚ด๋ถ€ ๋ฐ ์™ธ๋ถ€ ๋„คํŠธ์›Œํฌ(front-tier)์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ , ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ์˜ ์ง์ ‘์ ์ธ ์•ก์„ธ์Šค๋ฅผ ์ œํ•œํ•˜์—ฌ ์•ˆ์ „ํ•œ ์„œ๋น„์Šค ๊ตฌ์ถ•์„ ๋•์Šต๋‹ˆ๋‹ค.

docker-compose.yml๋กœ ํฌํŒ…: services๋“ค์— ๋„คํŠธ์›Œํฌ ์ง€์ •

โ€ข
๊ธฐ์กด
services: redis: image: redis:alpine db: image: postgres:15-alpine vote: build: ./vote ports: - 5001:80 result: build: ./result ports: - 5002:80 worker: build: ./worker
YAML
๋ณต์‚ฌ
โ€ข
๋ณ€๊ฒฝ
services: redis: โ€ฆ networks: - back-tier db: โ€ฆ networks: - back-tier vote: โ€ฆ networks: - back-tier - front-tier result: โ€ฆ networks: - back-tier - front-tier worker: โ€ฆ networks: - back-tier networks: back-tier: front-tier:
YAML
๋ณต์‚ฌ

docker-compose.yml๋กœ ํฌํŒ…: volumes ์ •์˜

โ€ข
์–ด๋Š ์ปจํ…Œ์ด๋„ˆ ์„œ๋น„์Šค์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณ„์†ํ•ด์„œ ์ €์žฅ๋˜์–ด์•ผ ํ•˜๋Š”๊ฐ€?
โ—ฆ
PostgreSQL
โ€ข
db์˜ ๋‚ด์šฉ์ด persistentํ•ด์•ผํ•จ โ‡’ ๋ณผ๋ฅจ ์ƒ์„ฑ (๋„ค์ž„๋“œ ๋ณผ๋ฅจ)
volumes: db-data:
YAML
๋ณต์‚ฌ
โ€ข
docker-compose.yml๋กœ ํฌํŒ…: services๋“ค์— ๋ณผ๋ฅจ ์ง€์ •
services: redis: db: vote: result: worker:
YAML
๋ณต์‚ฌ
services: redis: # db ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ๋””๋ ‰ํ† ๋ฆฌ ์žฅ์†Œ์™€ ๋„ค์ž„๋“œ ๋ณผ๋ฅจ์„ ๋งคํ•‘ db: volumes: - db-data:/var/lib/postgresql/data vote: result: worker: volumes: db-data:
YAML
๋ณต์‚ฌ

docker-compose.yml๋กœ ํฌํŒ…: vote ์„œ๋น„์Šค ๊ฐœ์„ 

โ€ข
depends_on : ์„œ๋น„์Šค๋“ค๊ฐ„์˜ ์˜์กด์„ฑ์ด ์žˆ์„ ๊ฒฝ์šฐ, ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์„œ๋น„์Šค๋“ค์„ ์—ฌ๊ธฐ ๊ธฐ์ˆ ํ•ด์•ผํ•œ๋‹ค.
โ—ฆ
๋” ๋‚˜์•„๊ฐ€์„œ ํ•ด๋‹น ์„œ๋น„์Šค์˜ health check๋„ ํฌํ•จํ•ด์คŒ
โ€ข
healthcheck : ํ•ด๋‹น ์„œ๋น„์Šค์˜ ๊ฑด๊ฐ•์„ ๋‚˜ํƒ€๋‚ด์ฃผ๋Š” ์ฒดํฌ๋ฅผ ๊ธฐ์ˆ 
โ€ข
docker-compose.yml์˜ command์™€ entrypoint
โ—ฆ
command: ์ด๋ฏธ์ง€ Dockerfile์˜ CMD๋ฅผ ๋ฎ์–ด์“ฐ๋Š”๋ฐ ์‚ฌ์šฉ
โ—ฆ
entrypoint: ์ด๋ฏธ์ง€ Dockerfile์˜ ENTRYPOINT๋ฅผ ๋ฎ์–ด์“ฐ๋Š”๋ฐ ์‚ฌ์šฉ
โ€ข
docker-compose.yml์˜ healthcheck
โ—ฆ
์—ญ์‹œ Dockerfile์—์„œ ๊ธฐ์ˆ  ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ์ด๋ฉฐ docker-compose์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฎ์–ด์“ฐ๊ธฐ ๊ฐ€๋Šฅ
healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] # 0 for success 1 for failure interval: 1m30s timeout: 10s # ์‹คํ–‰ ์‹œ๊ฐ„ 10์ดˆ ๋„˜์–ด๊ฐ€๋ฉด fail retries: 3 start_period: 40s
Docker
๋ณต์‚ฌ
โ€ข
docker-compose.yml์˜ depends_on
โ—ฆ
ํ•ด๋‹น ์„œ๋น„์Šค๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์œ„ํ•ด์„œ ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์„œ๋น„์Šค๋“ค์„ ์—ฌ๊ธฐ ๊ธฐ์ˆ 
โ–ช
short form:
depends_on: - db - redis
YAML
๋ณต์‚ฌ
โ–ช
long form:
depends_on: db: condition: service_healthy redis: condition: service_started
YAML
๋ณต์‚ฌ
depends_on์˜ condition์œผ๋กœ ๊ฐ€๋Šฅํ•œ ๊ฐ’
โ–ช
service_started:
โ€ข
์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€
โ–ช
service_healthy:
โ€ข
์˜์กด์„ฑ์ด ๊ฑด๊ฐ• ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” healthcheck์— ๋”ฐ๋ผ ์‹œ์ž‘ ์ „์— "๊ฑด๊ฐ•"ํ•œ ์ƒํƒœ์ธ์ง€ ํ™•์ธ.
โ€ข
True or False โ‡’ 0 for success 1 for failure
โ–ช
service_completed_successfully:
โ€ข
์˜์กด์„ฑ์— ์ข…์†๋œ ์„œ๋น„์Šค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๊ณ , ์™„๋ฃŒ ํ›„์— ์ข…์† ์„œ๋น„์Šค๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์ฒ˜์Œ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๋Š” ์„œ๋น„์Šค

docker-compose.yml๋กœ ํฌํŒ…: db ์„œ๋น„์Šค ๊ฐœ์„ 

โ€ข
์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด Postgres DB ์„ค์ •์ด ๋จ. ์ด์— ๋Œ€ํ•ด์„œ ์•ž์„œ ์‚ดํŽด๋ณด์•˜์Œ
โ€ข
host volume๊ณผ named volume์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ
โ—ฆ
host volume : ์ง์ ‘ ํ˜ธ์ŠคํŠธ pc์˜ ๋””๋ ‰ํ† ๋ฆฌ ์ฃผ์†Œ์™€ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ์ฃผ์†Œ๋ฅผ ๋งคํ•‘
โ€ข
docker-compose.yml์˜ environment
โ—ฆ
ํ•ด๋‹น ์„œ๋น„์Šค๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์‹คํ–‰๋  ๋•Œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋“ค์„ ์ง€์ • (Dockerfile์˜ ENV)
โ—ฆ
2๊ฐ€์ง€ ๋ฌธ๋ฒ•์ด ์กด์žฌ
โ–ช
Map ๋ฌธ๋ฒ• โ†’ ์œ„์˜ docker compose file์€ ์ด ๊ฒƒ์„ ์‚ฌ์šฉ
environment: RACK_ENV: development SHOW: "true" USER_INPUT:
Docker
๋ณต์‚ฌ
โ–ช
Array ๋ฌธ๋ฒ•:
environment: - RACK_ENV=development - SHOW=true - USER_INPUT
Docker
๋ณต์‚ฌ

docker-compose.yml๋กœ ํฌํŒ…: redis ์„œ๋น„์Šค ๊ฐœ์„ 

โ€ข
volume, health check, network ์„ค์ •

docker-compose.yml๋กœ ํฌํŒ…: worker ์„œ๋น„์Šค ๊ฐœ์„ 

โ€ข
build ํ‚ค์›Œ๋“œ ๋ฐ‘์— ๋นŒ๋“œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๋” ๋‚จ๊ฒจ์„œ docker compose ์ •๋ณด๋“ค์„ ๊ธฐ๋ก ๊ฐ€๋Šฅ
โ—ฆ
๋„์ปค ํŒŒ์ผ ๋ช…, ๋„์ปคํŒŒ์ผ ์œ„์น˜ํ•œ ๋””๋ ‰ํ† ๋ฆฌ
build: context: ./my_app # ๋„์ปคํŒŒ์ผ์ด ์œ„์น˜ํ•œ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ dockerfile: Dockerfile.prod # ๋„์ปค ํŒŒ์ผ ๋ช… args: - ENV=production # ๋นŒ๋“œ ์‹œ์— ์‚ฌ์šฉํ•  ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •
Docker
๋ณต์‚ฌ

docker-compose.yml๋กœ ํฌํŒ…: result ์„œ๋น„์Šค ๊ฐœ์„  (node)

โ€ข
entrypoint : Dockerfile์˜ entrypoint๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ

์ตœ์ข… Docker-compose.yml ๋ฆฌ๋ทฐ

โ€ข
์ฃผ์˜ : ๋‹ค์‹œ ํ•œ๋ฒˆ Monterey Mac์—์„œ ํฌํŠธ 5000๋ฒˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ์— vote ์•ฑ์˜ ํฌํŠธ๋ฒˆํ˜ธ๋ฅผ ์ˆ˜์ •ํ•ด์•ผํ•จ (์•„๋ฌด port๋ฅผ ๋ถ€์—ฌํ•  ๊ฒƒ, 5001, 5002 ์ œ์™ธ)
โ€ข
vote์™€ result์˜ ํฌํŠธ๋ฒˆํ˜ธ๋ฅผ ๊ฐ๊ฐ 5001๊ณผ 5002๋กœ ์ˆ˜์ •ํ•œ ๋ฒ„์ „์ด ์œ„์˜ ๋ฒ„์ „
# version is now using "compose spec" # v2 and v3 are now combined! # docker-compose v1.27+ required services: vote: build: ./vote # use python rather than gunicorn for local dev command: python app.py depends_on: redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 15s timeout: 5s retries: 3 start_period: 10s volumes: - ./vote:/app ports: - "5000:80" networks: - front-tier - back-tier result: build: ./result # use nodemon rather than node for local dev entrypoint: nodemon server.js depends_on: db: condition: service_healthy volumes: - ./result:/app ports: - "5001:80" - "5858:5858" networks: - front-tier - back-tier worker: build: context: ./worker depends_on: redis: condition: service_healthy db: condition: service_healthy networks: - back-tier redis: image: redis:alpine volumes: - "./healthchecks:/healthchecks" healthcheck: test: /healthchecks/redis.sh interval: "5s" networks: - back-tier db: image: postgres:15-alpine environment: POSTGRES_USER: "postgres" POSTGRES_PASSWORD: "postgres" volumes: - "db-data:/var/lib/postgresql/data" - "./healthchecks:/healthchecks" healthcheck: test: /healthchecks/postgres.sh interval: "5s" networks: - back-tier # this service runs once to seed the database with votes # it won't run unless you specify the "seed" profile # docker compose --profile seed up -d seed: build: ./seed-data profiles: ["seed"] depends_on: vote: condition: service_healthy networks: - front-tier restart: "no" volumes: db-data: networks: front-tier: back-tier:
YAML
๋ณต์‚ฌ
์ฐธ๊ณ ๋กœ ์œ„์˜ docker compose file์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์‹คํ–‰์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. (๊ทธ์ € ์ด๋ ‡๊ฒŒ ๊ฐœ์„ ์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์•Œ๋ ค์ฃผ๊ณ  ์‹ถ์—ˆ์„ ๋ฟ) โ†’ ์•„๋ž˜์˜ ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋‹น์‹ ์€ ์ด๋ฏธ..
example-voting-app-db-1 | 2023-07-25 15:45:47.023 UTC [1] LOG: database system is ready to accept connections dependency failed to start: container example-voting-app-db-1 is unhealthy
Python
๋ณต์‚ฌ

Reference

[Docker] ๋„์ปค ์ปดํฌ์ฆˆ(Docker compose) - ๊ฐœ๋… ์ •๋ฆฌ ๋ฐ ์‚ฌ์šฉ๋ฒ•
์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋„์ปค ์ปดํฌ์ฆˆ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋„์ปค ์ปดํฌ์ฆˆ๋ž€? ๋„์ปค ์ปดํฌ์ฆˆ๋Š” ๋‹จ์ผ ์„œ๋ฒ„์—์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์˜ ์„œ๋น„์Šค๋กœ ์ •์˜ํ•ด ์ปจํ…Œ์ด๋„ˆ์˜ ๋ฌถ์Œ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๊ด€๋ฆฌ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๋„์ปค ์ปดํฌ์ฆˆ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•˜๋‚˜์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋™์ž‘ํ•  ๋•Œ ๋„์ปค ์ปดํฌ์ฆˆ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ด๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ๊ฐ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ•˜๋‚˜์”ฉ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ์›น ์„œ๋ฒ„ ์ปจํ…Œ์ด๋„ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปจํ…Œ์ด๋„ˆ ๋‘ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ๊ฐ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์•„๋ž˜์™€ ๊ฐ™์ด ๋‘๊ฐœ์˜ run ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. $ docker run --name wordpress_db -d mysql:8 $ docker run -d -p 8080:80 \ --l..
์‹ค์Šต์œผ๋กœ ๋ฐฐ์šฐ๋Š” Docker ์ž…๋ฌธ | 4. Docker Compose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ ๋ฐฐํฌ
์ง€๊ธˆ๊นŒ์ง€๋Š” ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€ ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ทจ๊ธ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ง„ํ–‰ํ•ด๋ดค๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ ๊ฐœ๋ฐœ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ Web ์„œ๋ฒ„ ๋“ฑ์˜ ์—ฌ๋Ÿฌ ๊ณต์ •์„ ์กฐํ•ฉํ•˜์—ฌ ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. Docker๋ฅผ ์‚ฌ์šฉํ•œ ์‹œ์Šคํ…œ์—์„œ๋Š” ํ•˜๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ๋ฅผ ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ์— ํ• ๋‹นํ•œ๋‹ค(Each container should have only one concern) ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋„ ๊ถŒ์žฅ๋˜๊ณ  ํ•„์—ฐ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ๋‹ค. ๋ณธ ๋ฌธ์„œ๋Š” ๊ฐœ๋ฐœ ๋ฐ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์œ„ํ•œ ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ์—์„œ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ Docker Compose๋ผ๋Š” ๋„๊ตฌ๋ฅผ ์†Œ๊ฐœํ•œ๋‹ค. ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ๋„๊ตฌ Docker Compose ๊ฐœ์š” Docker Compose๋Š” ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋กœ ๊ตฌ์„ฑ๋œ Docker ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ค์ •์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ด๋‹ค.