前面我們提到compose就是個協助多容器開發的工具,也因為該工具的誕生,讓許許多多原本使用scripts來啟動多容器的程序員得以更簡單的開發。所以此章節我們將會把Day-10的程式碼的程式碼從script轉化成使用docker-compose做containers的部署。
P.s 還沒看過Day-10 撰寫 Docker專用的Script的程式碼的朋友可以建議先去服用!
docker-compose的版本,目前到version 3,每一版間都有些許的差異,有興趣者請點擊下方連結
https://docs.docker.com/compose/compose-file/
version: '3'
主要的容器服務都撰寫在此。
version: '3'
services:
創建後的Container名稱
version: '3'
services:
nginx:
container_name: nginx
Container所使用的Image
version: '3'
services:
nginx:
container_name: nginx
image: nginx
Container所bind的port與expose的port
version: '3'
services:
nginx:
container_name: nginx
image: nginx
ports:
- "8080:80"
到這裡我們已經創造了一個簡單的docker-compose,那現在我們來測試看看!
啟動docker-compose時,若在yaml中沒有為每個Container指定network,則會創建一個local_default的預設bridge network,並且Containers都會用它。
$ docker-compose up
Creating network "local_default" with the default driver
Creating nginx ... done
Attaching to nginx
nginx | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
nginx | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
那我們來關閉它吧!
docker-compose down的同時會移除所有的Containers,並且移除所有相關的resources,像是network、volumes等。
$ docker-compose down -v
Stopping nginx ... done
Removing nginx ... done
Removing network local_default
我們接下來練習一下吧,以Day-10 撰寫 Docker專用的Script的程式碼為例:
假設我們需要下列三個不同的Containers,數字代表port的號碼,綠色圈代表Expose port,紅色圈代表Expose port並映射到本地的相同port。
以下是原有script的nginx部分,那我們就先來convert nginx並建立bridge network吧!也就是紅色部分
#!/bin/bash
#!/bin/bash
env=$1
docker network create ironman-net
if [ "$env" == "prd" ];then
docker run -e ENVIRONMENT="$env" --env-file prd.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
else
docker run -e ENVIRONMENT="stg" --env-file stg.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
fi
docker run --net=ironman-net --name redis -d -p 6379:6379 redis:4.0
docker run --net=ironman-net --name nginx -d -p 80:80 -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v $(pwd)/nginx/default.conf:/etc/nginx/conf.d/default.conf nginx
在上方nginx啟動程式碼我們能發現:
version: '3'
services:
nginx:
container_name: nginx
image: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
restart: always
networks:
- ironman-net
networks:
ironman-net:
driver: bridge
如上所示,我們選擇version 3的docker-compose,創建了一個container name為nginx的service,並且expose 80 port並映射到本地的80 port,然後掛載了兩個volumes,設定service restart機制為always,最後則是創建一個bridge network並讓nginx使用它。
這部分就如法炮製囉,我們來轉換綠色部分
#!/bin/bash
#!/bin/bash
env=$1
docker network create ironman-net
if [ "$env" == "prd" ];then
docker run -e ENVIRONMENT="$env" --env-file prd.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
else
docker run -e ENVIRONMENT="stg" --env-file stg.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
fi
docker run --net=ironman-net --name redis -d -p 6379:6379 redis:4.0
docker run --net=ironman-net --name nginx -d -p 80:80 -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v $(pwd)/nginx/default.conf:/etc/nginx/conf.d/default.conf nginx
我們轉換redis會需要:
version: '3'
services:
nginx:
container_name: nginx
image: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
restart: always
networks:
- ironman-net
redis:
container_name: redis
image: redis:4.0
ports:
- "6379:6379"
restart: always
networks:
- ironman-net
networks:
ironman-net:
driver: bridge
基本上就是如法泡製nginx,轉換過程相當的容易。
最後則是轉換藍色部分
#!/bin/bash
#!/bin/bash
env=$1
docker network create ironman-net
if [ "$env" == "prd" ];then
docker run -e ENVIRONMENT="$env" --env-file prd.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
else
docker run -e ENVIRONMENT="stg" --env-file stg.env \
--net=ironman-net --name ironman -d -v $(pwd)/app:/usr/src/app/app ghjjhg567/ironman:latest
fi
docker run --net=ironman-net --name redis -d -p 6379:6379 redis:4.0
docker run --net=ironman-net --name nginx -d -p 80:80 -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v $(pwd)/nginx/default.conf:/etc/nginx/conf.d/default.conf nginx
我們轉換ironman會需要
version: '3'
services:
nginx:
container_name: nginx
image: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
restart: always
networks:
- ironman-net
redis:
container_name: redis
image: redis:4.0
ports:
- "6379:6379"
restart: always
networks:
- ironman-net
ironman:
container_name: ironman
image: ghjjhg567/ironman:latest
volumes:
- ./app/:/usr/src/app/app
env_file:
- prd.env
restart: always
networks:
- ironman-net
networks:
ironman-net:
driver: bridge
這樣就大功告成了!但是...肯定有冰雪聰明的小夥伴想問,那如果想啟動staging環境的web service呢?
這邊我以前做法會是準備另一個yaml檔是啟動staging環境的,如此一來就能在該yaml來使用stage的環境變數,有興趣的小夥伴在麻煩去 day-11 branch下載程式碼。但但但是,其實還有著另一作法,這邊會在day-13時解說,敬請期待!
本篇章所有程式碼將放在下面的github project當中的branch day-12
https://github.com/Neskem/ironman_2020/tree/day-12
今天我們解說了基本docker-compose.yaml的撰寫,並且將之前的啟動Containers的script轉換成了compose的yaml,那也大大的降低啟動多容器的難度並且也增加了可讀性,在下次章節會再更深入分享一些compose的運用,有興趣的夥伴也可以期待一下,謝謝。
恭喜大家學會了基本docker-compose.yaml的撰寫,也會自己的Docker-Compose獸添加了些經驗!
https://docs.docker.com/compose/compose-file/