Github
常常一個專案內, 主要的業務服務會有一些依賴的服務一起搭配, 進而完成工作.
常見的其他服務有 Nginx DB(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:
        ports:
          - 80:80
        environment:
          PRODUCTION: 'true'
      backgroundservice:
        build: 
          context: ../
          dockerfile: docker/CrawlerDockerfile
        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
    指定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:
        build: .
        depends_on:
          - redis
      redis:
        image: redis
        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版本
  • docker-compose up [options] [SERVICE...]
  • 等於一整組的動作, 重新create container, start container, link each
  • -d 將在後台運行
  • --scale SERVICE_NAME=NUM, 用來水平伸縮指定service的數量
  • docker-compose stop [options] [SERVICE...]
  • 停止狀態是running的容器
  • docker-compose rm [options] [SERVICE...]
  • 會刪除所有狀態是stopped的容器, 所以建議事先使用上面的stop來停止容器後再進行刪除
  • docker-compose ps [options] [SERVICE...]
  • 列出容器清單
  • 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 的運作

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