7.12 HEALTHCHECK 健康檢查
7.12.1 基本語法
HEALTHCHECK [選項] CMD <指令>
HEALTHCHECK NONE
HEALTHCHECK 指令告訴 Docker 如何判斷容器狀態是否正常。這是保障服務高可用的重要機制。
7.12.2 為什麼需要 HEALTHCHECK
在沒有 HEALTHCHECK 之前,Docker 只能透過 程序退出碼 來判斷容器狀態。問題場景:
- Web 服務死鎖,無法回應請求,但程序仍在執行
- 資料庫正在啟動中,尚未準備好接受連線
- 應用陷入死迴圈,CPU 爆滿但程序存活
引入 HEALTHCHECK 後: Docker 定期執行指定的檢查指令,根據回傳值判斷容器是否 『健康』。
容器狀態轉換:
Starting ──成功──> Healthy ──失敗N次──> Unhealthy
▲ │
└──────成功──────┘
7.12.3 基本用法
Web 服務檢查
# 注:nginx 映象推薦使用具體的版本標籤(如 nginx:1.28-alpine)
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -fs http://localhost/ || exit 1
指令回傳值
0:成功 (healthy)1:失敗 (unhealthy)2:保留值 (不使用)
常用選項
| 選項 | 說明 | 預設值 |
|---|---|---|
--interval |
兩次檢查的間隔 | 30s |
--timeout |
檢查指令的超時時間 | 30s |
--start-period |
啟動緩衝期 (期間失敗不計入次數) | 0s |
--retries |
連續失敗多少次標記為 unhealthy | 3 |
7.12.4 遮蔽健康檢查
如果基礎映象定義了 HEALTHCHECK,但你不想使用它:
FROM my-base-image
HEALTHCHECK NONE
7.12.5 常見檢查指令碼
HTTP 服務
使用 curl 或 wget:
## 使用 curl
HEALTHCHECK CMD curl -f http://localhost/ || exit 1
## 使用 wget(Alpine 預設包含)
HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
資料庫
## MySQL
HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
## Redis
HEALTHCHECK CMD redis-cli ping || exit 1
自定義指令碼
COPY healthcheck.sh /usr/local/bin/
HEALTHCHECK CMD ["healthcheck.sh"]
7.12.6 在 Compose 中使用
可以在 compose.yaml (或 docker-compose.yml) 中覆蓋或定義健康檢查:
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
帶健康檢查的依賴啟動:
services:
web:
depends_on:
db:
condition: service_healthy # 等待 db 變健康才啟動 web
db:
image: mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
7.12.7 檢視健康狀態
## 檢視容器狀態(包含健康訊息)
$ docker ps
CONTAINER ID STATUS
abc123 Up 1 minute (healthy)
def456 Up 2 minutes (unhealthy)
## 檢視詳細健康日誌
$ docker inspect --format '{{json .State.Health}}' mycontainer | jq
{
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "...",
"End": "...",
"ExitCode": 0,
"Output": "..."
}
]
}
7.12.8 最佳實踐
1. 避免副作用
健康檢查會被頻繁執行,不要在檢查指令碼中進行寫操作或消耗大量資源的操作。
2. 使用輕量級工具
優先使用映象中已有的工具 (如 wget),避免為了健康檢查安裝龐大的依賴 (如 curl)。
3. 設定合理的 Start Period
應用啟動可能需要時間 (如 Java 應用)。設定 --start-period 可以防止在啟動階段因檢查失敗而誤判。
## 給應用 1 分鐘啟動時間
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
4. 只檢查核心依賴
健康檢查應主要關注 當前服務 是否可用,而不是檢查其下游依賴 (資料庫等)。下游依賴的檢查應由應用邏輯處理。
5. 與容器編排平台的關係
不同平台對 HEALTHCHECK 的支援有所不同:
- Docker Compose:直接使用 Dockerfile 中定義的 HEALTHCHECK,也可在
compose.yaml中覆蓋 - Docker Swarm:使用 HEALTHCHECK 進行服務健康判斷和捲動更新決策
- Kubernetes:忽略 Dockerfile 中的 HEALTHCHECK,使用自己的
livenessProbe和readinessProbe機制
如果應用同時部署在 Docker Compose 和 Kubernetes 環境中,建議在 Dockerfile 中保留 HEALTHCHECK(供 Compose 使用),同時在 Kubernetes 的 Pod 設定中定義對應的探針。