iT邦幫忙

2021 iThome 鐵人賽

DAY 19
1
Software Development

系統與服務雜談系列 第 19

多容器編排與管理 Docker Compose簡介

上篇回顧
設定檔格式 YAML

Docker太多文章介紹了, 小弟我K8S也沒那麼熟稔
就介紹自己熟的Compose吧

Docker的相關入門能參考
30 天與鯨魚先生做好朋友
30天與 Docker 做好朋友:跟鯨魚先生一同探索開發者的大平台(iT邦幫忙鐵人賽系列書)

docker compose

Docker Compose

Github
常常一個專案內, 主要的業務服務會有一些依賴的服務一起搭配, 進而完成工作.
常見的其他服務有NginxDB(MySQL, Postgre...)NoSQL(Redis、Mongo...)SMTP...etc
至於這compose需要什麼服務, 就看各業務服務需要哪些了.

利用DockerCompose來管理容器, 或者配置各容器需要掛載到哪個network、volume...,
都能透過開發者定義的docker-compose.yml文件, 來定義一組相關連的容器為一個Project.
所以上篇才介紹一下YAML

Docker-compose的圖, 也正好說明,
一隻章魚?魷魚?有好幾隻手, 每個觸手上管理著一個container, 任章魚把玩

跟Dockfile的差異

其實只是管理便利性地差異,
Docker-compose還是要先安裝好Docker, 當然Compose也能來編譯原本寫好的Dockerfile
如果自己是喜歡寫Makefile或Shell快速管理的高手, 當然也是可以不需要Compose.

Compose中兩個重要概念

  • Service
    • 一個應用的容器
  • Project
    • 由一組關聯的應用容器組成的一個完整業務單元, 在docker-compose.yml中定義.

Compose默認管理的對象是Project, 透過命令對Project中的容器進行生命週期管裡

以下只是範例, 並不真能跑, 因為我沒放web專案的代碼

version: "3"
services:
  web:
    ports:
      - 80:80
    environment:
      PRODUCTION: 'true'
  backgroundservice:
    build: 
      context: ../
      dockerfile: docker/CrawlerDockerfile
  db:
    image: mysql:8.0
    ports:
      - "3306:3306"
    command: [
      "--server-id=1",
      "--default-authentication-plugin=mysql_native_password"
    ]
    volumes:
      - ./db.cnf:/etc/mysql/conf.d/mysqld.cnf
      - ./sql:/docker-entrypoint-initdb.d

每個service都需要透過image指令來指定image名稱與版本(如web和db)
又或者透過build指令來編譯Dockfile, 建構出image(如backgroundservice)

build

context
args
指定Dockfile所在的文件位置, 可以是絕對位置或相對位置),
Compose會自動利用這路徑下的Dockfile來自動構建出image, 然後使用該image進行容器的設定

---
version: "3.9"
services:
  webapp:
    build: ./dir #直接指定路徑, 前提要dockfile檔名剛好是Dockerfile
...

---
version: "3.9"
services:
  webapp:
    build:
      context: ./dir #透過context來指定路徑
      dockerfile: Dockerfile-alternate #說明要執行編譯的Dockfile檔名
      args: # 指定編譯image時, 所需要的arguments
        buildno: 1
...

image

指定image名稱, 版本, 甚至能直接指定image ID(但我不推薦,, 沒閱讀性)

command

用來覆蓋容器啟動後默認執行的動作, 跟dockerfile的CMD類似的
在推薦的書本裡Chap5也有提到

expose

開放port給container連線, 但沒有映射到host上

expose:
  - "3000"
  - "8000"

ports

將port綁定在host上, 然後就能在host的環境, 與容器做交互

depends_on

當使用docker-compose up時, 依照依賴順序, 以範例來說會先啟動db和redis,再來啟動web
docker-compose stop時, 一樣反序的關閉容器.

Control startup and shutdown order in Compose
但! 只是啟動順序, 不代表web被啟動完成時, db已經啟動完成.
以下是官網的說明, 就只有啟動, 並不會等待容器的狀態到Ready

However, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running. There’s a good reason for this.

官網推薦的作法是在透過一隻wait-for-it.sh,
在依賴方執行透過docker-compose的command或直接寫在dockerfile的CMD去執行;
vishnubob/wait-for-it
eficode/wait-for

或是被依賴方透過healthcheck去執行CMD, DockerLibrary有提供一些服務的HealthCheck腳本
透過healthcheck的話, 請別用until-do-done,
透過命令提供的options: interval, timeout, start-period retries來做循環
直接執行一次成功回應exit 0, 失敗回應exit 1
ps 這方法有版本限制問題

version: "3.9"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

docker-compose太多config options了, 大家能自己到官網學習

docker-compose 常見命令

docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

options:

  • -f compose文件名稱, 預設是docker-compose.yml
  • -p 指定project name, 預設用所在目錄名稱當專案名稱, 建議指定, 方便管理
  • --verbose 輸出詳細的debug資訊

commands:

  • build
    • docker-compose build [options] [SERVICE...]
    • 重新build該項目所有service的image
      • --force-rm 刪除臨時容器
      • --no-cache 就不用cache
      • --pull 嘗試拉取最新的image版本
  • config
    • 驗證compose檔案格式, 錯誤會顯示錯誤原因
    • 好用! YAML格式太吃indent了XD
  • up
    • docker-compose up [options] [SERVICE...]
    • 等於一整組的動作, 重新create container, start container, link each
    • -d 將在後台運行
    • --scale SERVICE_NAME=NUM, 用來水平伸縮指定service的數量
  • stop
    • docker-compose stop [options] [SERVICE...]
    • 停止狀態是running的容器
  • rm
    • docker-compose rm [options] [SERVICE...]
    • 會刪除所有狀態是stopped的容器, 所以建議事先使用上面的stop來停止容器後再進行刪除
  • ps
    • docker-compose ps [options] [SERVICE...]
    • 列出容器清單
  • logs
    • docker-compose logs [options] [SERVICE...]
    • 如果沒指定service name, 則把所有service的log都輸出

Podman-Compose

關於Docker desktop的替代方案之一的Podman, 也支持compose, 所以轉換上挺方便的

本日小結

Docker-compose對於一個專案內有多個容器的需求時, 管理容器的生命週期以及設定檔的撰寫非常便利.
且由於是一個專案內要設定多個service, 所以上一篇學到的anchor&alias*, 應該能在很多開源專案內的yml常看到.

雖然Docker漸漸地被冷漠?
但為了方便開發者與運維人員便利管理容器, 且Docker真的太夯,
基本替代方案出來, 還是兼容Dockerfile與Docker-compose.

相關說明能參考
30天分享那些年我怎麼理解 kubernetes 的運作

ps

Dokcker-compose V2最近剛釋出,
V1是用Python開發的, V2則是用Go
使用指令上, V1如文章是docker-compose, V2則是docker compose
詳情能看Compose Github連結


上一篇
設定檔格式 YAML
下一篇
分布式可觀測性 Logging 淺談
系列文
系統與服務雜談32

1 則留言

1
json_liang
iT邦新手 4 級 ‧ 2021-10-04 00:34:04

感謝雷N分享 讓我找到 k8s 好文章

我要留言

立即登入留言