3 個使用 docker compose 的必備指令

Posted on  Dec 21, 2023  in  Docker  by  Amo Chen  ‐ 3 min read

本文將介紹 3+1 個 docker compose 的指令,讓我們能夠在執行 docker compose up 指令之前提早偵錯 docker compose file 可能存在的問題與 docker 預定的容器啟動程序,以及以指令繪製出容器之間的相依關係。

本文環境

$ brew install graphviz

本文範例專案結構

以下是本文範例的專案結構,Dockerfile 用以編譯執行 app.py 的容器,compose.yaml 則是架設開發環境的 docker compose file:

.
├── Dockerfile
├── app.py
└── compose.yaml

本文使用 Python Flask 架設 1 個簡單的 Web server 作為模擬之用,如果對 Python 不熟也沒關係,不影響教學進行,以下是 app.py 的內容,該程式碼主要會連線到 Redis 對 hits 這個 key 值做遞增操作,每 GET app.py/ 就做 1 次遞增。

app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hit count: {}\n'.format(count)

以下是 Dockerfile 的內容。

Dockerfile

FROM python:3.8-alpine
WORKDIR /app
ENV FLASK_APP=app.py
RUN apk add --no-cache gcc musl-dev linux-headers
RUN pip install flask redis
EXPOSE 5000
COPY . .
CMD ["flask", "run", "--host", "0.0.0.0"]

以下是 compose.yaml 的內容,可以看到開發環境需要執行 Redis 與我們所編譯的 Web server 。

compose.yaml

services:
  web:
    build: .
    ports:
      - "8000:5000"
    environment:
      - DEBUG_MODE=${DEBUG_MODE}
    depends_on:
      redis:
        condition: service_healthy
  redis:
    image: "redis:alpine"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      timeout: 10s
      retries: 3
      start_period: 10s

docker compose config 列印最終的 Docker compose file

撰寫完 docker compose file 之後,可以先用以下指令查看是否最終的 docker compose file 符合你的預期,這對有設定環境變數的 docker compose file 相當有幫助,因為遺漏環境變數設定是使用 docker compose 的常見問題:

$ docker compose config

以本文範例為例,執行上述指令之後結果如下:

WARN[0000] The "DEBUG_MODE" variable is not set. Defaulting to a blank string.
name: myrepo
services:
  redis:
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
      timeout: 10s
      retries: 3
      start_period: 10s
    image: redis:alpine
    networks:
      default: null
  web:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      redis:
        condition: service_healthy
        required: true
    environment:
      DEBUG_MODE: ""
    networks:
      default: null
    ports:
      - mode: ingress
        target: 5000
        published: "8000"
        protocol: tcp
networks:
  default:
    name: myrepo_default

從結果可以看到,可以看到警告訊息(warning)提示 DEBUG_MODE 環境變數未設定,因此設定為空字串,善用這個指令可以提早檢查可能存在的錯誤,減少執行 docker compose up 之後才發現有問題的情況。

docker compose up --dry-run 檢查 docker compose 預定的啟動程序與情況

執行 docker compose up 指令時可以加上 --dry-run 參數,該參數會使 docker compose 以模擬的方式執行,不會真實啟動相關的容器,對於檢查容器啟動的程序與情況相當有用:

$ docker compose up --dry-run

上述指令執行結果如下:

WARN[0000] The "DEBUG_MODE" variable is not set. Defaulting to a blank string.
[+] Building 0.0s (0/0)
docker:orbstack
[+] Running 2/0
 ✔ DRY-RUN MODE -  Container myrepo-redis-1  Recreated
 ✔ DRY-RUN MODE -  Container myrepo-web-1    Recreated
end of 'compose up' output, interactive run is not supported in dry-run mode

可以看到 docker compose 直接啟動 redisweb 容器,沒有編譯 web 容器的過程,這是 docker compose 預設的機制,如果已經有相對應的 images 存在,就會直接使用,不會進行編譯後再啟動,這就是為什麼我們如果改了相關設定、程式碼都要重新編譯相關的 docker images 才會發生作用。

docker compose up --build 強制重新編譯 Docker images

前文提到 docker compose 預設的機制,如果已經有相對應的 images 存在,就會直接使用,不會進行編譯後再啟動。

除了自己手動重新編譯 docker image 之外,也可以加上 --build 參數讓 docker compose up 指令重新編譯 docker image:

$ docker compose up --build --dry-run

上述指令加上 --dry-run 參數,可以從以下結果看到多了 build service web 步驟:

WARN[0000] The "DEBUG_MODE" variable is not set. Defaulting to a blank string.
[+] Building 0.0s (0/0)                                             docker:orbstack
[+] Running 5/0
 ✔ DRY-RUN MODE -    build service web
 ✔ DRY-RUN MODE -  ==> ==> writing image dryRun-ca84d1343b96baa8137c943ed1860e522cacb238
 ✔ DRY-RUN MODE -  ==> ==> naming to myrepo-web
 ✔ DRY-RUN MODE -  Container myrepo-redis-1      Recreated
 ✔ DRY-RUN MODE -  Container myrepo-web-1        Recreated
end of 'compose up' output, interactive run is not supported in dry-run mode

同場加映 docker compose alpha viz 繪製容器相依關係圖

docker compose alpha viz 是仍處於實驗階段的指令,不過這個指令可以將容器之間的相依關係圖以 Graphviz 語法顯示,所以可以用 pipe 交由 Graphviz 繪製容器相依關係圖,對於寫文件或者向團隊成員解釋開發環境的架構相當有用。

以下是將容器關係圖以 SVG 檔案輸出的指令:

$ docker compose alpha viz | dot -Tsvg > output.svg

如果打開 output.svg 就會看到其關係, web 依賴 redis 容器:

output.svg



如果需要加上額外資訊的話,可以加上以下參數:

  • --image 顯示 docker image 名稱
  • --networks 顯示網路資訊
  • --ports 顯示容器開放的通訊埠

總結

docker compose 是相當方便的工具,但如果能懂得它提供的幾個參數將會提升使用它的效率,會比起執行 docker compose up 再除錯來得更好。

以上!

Enjoy!

References

Overview of docker compose CLI

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!