iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
DevOps

Docker獸 究極進化 ~~ Kubernetes獸系列 第 12

Day-12 煉成 Docker-Compose YAML

前言

前面我們提到compose就是個協助多容器開發的工具,也因為該工具的誕生,讓許許多多原本使用scripts來啟動多容器的程序員得以更簡單的開發。所以此章節我們將會把Day-10的程式碼的程式碼從script轉化成使用docker-compose做containers的部署。

P.s 還沒看過Day-10 撰寫 Docker專用的Script的程式碼的朋友可以建議先去服用!

Docker-Compose yaml basic key

version:

docker-compose的版本,目前到version 3,每一版間都有些許的差異,有興趣者請點擊下方連結

https://docs.docker.com/compose/compose-file/

version: '3'

service:

主要的容器服務都撰寫在此。

version: '3'
services:

service/<service>/container_name:

創建後的Container名稱

version: '3'
services:
  nginx:
    container_name: nginx

service/<service>/image:

Container所使用的Image

version: '3'
services:
  nginx:
    container_name: nginx
    image: nginx

service/<service>/port:

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

Requirements

我們接下來練習一下吧,以Day-10 撰寫 Docker專用的Script的程式碼為例:

假設我們需要下列三個不同的Containers,數字代表port的號碼,綠色圈代表Expose port,紅色圈代表Expose port並映射到本地的相同port。

  • Web Service: 提供後端服務,需要開放容器port 8100,讓nginx能導流進來。
  • Nginx:用來redirect做load balance以及返回靜態物件,需要開放容器80port並且需要映射到本地port 80。
  • Redis:用來儲存Web Service的Cache,需開放容器port 6379,並且我們也映射到本地port 6379,讓我們隨時能查看Redis資料。

https://ithelp.ithome.com.tw/upload/images/20200927/20129737HWBpydrVCx.png

Convert Nginx

以下是原有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啟動程式碼我們能發現:

  1. nginx需要bridge network ironman-net
  2. nginx的container name為nginx
  3. nginx 需要expose 80 port 並映射到本地的80 port
  4. nginx需要掛載兩個config檔
  5. 他是用docker hub的nginx docker file啟動,並且沒有指定tag
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使用它。

Convert redis

這部分就如法炮製囉,我們來轉換綠色部分

#!/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會需要:

  1. reids需要bridge network ironman-net
  2. redis的container name為redis
  3. redis需要expose 6379 port並映射至本地 6379 port
  4. 它是選用docker hub的redis 映像檔,並指定版本為4.0
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,轉換過程相當的容易。

Convert web service

最後則是轉換藍色部分

#!/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會需要

  1. web service匯入環境變數檔案
  2. web service需要bridge network ironman-net
  3. web service的container name為ironman
  4. 它是選用docker hub的ghjjhg567/ironman:latest這個映像檔。
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 Repo

本篇章所有程式碼將放在下面的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://ithelp.ithome.com.tw/upload/images/20200927/20129737sKRCIPaKDT.png

Reference

https://docs.docker.com/compose/compose-file/


上一篇
Day-11 初出 Docker-Compose
下一篇
Day-13 熟悉 Docker-Compose 進階功能
系列文
Docker獸 究極進化 ~~ Kubernetes獸30

尚未有邦友留言

立即登入留言