在使用docker-compose的過程中,很多程式都提供了健康檢查(healthcheck)的方法,通過健康檢查,應用程式能夠在確保其依賴的程式都已經啟動的前提下啟動,減少各種錯誤的發生,同時,合理設計的健康檢查也能夠提供給外界關於應用程式狀態的一些信息。 大多數docker鏡像的詳細說明中,會交 ...
在使用docker-compose的過程中,很多程式都提供了健康檢查(healthcheck)的方法,通過健康檢查,應用程式能夠在確保其依賴的程式都已經啟動的前提下啟動,減少各種錯誤的發生,同時,合理設計的健康檢查也能夠提供給外界關於應用程式狀態的一些信息。
大多數docker鏡像的詳細說明中,會交代如何進行健康檢查,.NET 6也提供了文檔。也有其他人寫了文章說了更細節的內容。
實踐一下,現在docker-compose裡面是這樣:
version: '3.7'
services:
postgres:
container_name: postgres-container
image: postgres:13
volumes:
- ./postgres_data:/var/lib/postgresql/data/pgdata
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: "123456"
PGDATA: "/var/lib/postgresql/data/pgdata"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- dotnet-network
dotnet-service:
image: dotnet-service:latest
container_name: dotnet-service-container
ports:
- 5000:5000
build:
context: ./TestWeb/
dockerfile: ./TestWeb/Dockerfile
environment:
# - ASPNETCORE_ENVIRONMENT=Docker
- ASPNETCORE_URLS=http://*:5000
- App__SelfUrl=http://*:5000
restart: on-failure
depends_on:
postgres:
condition: service_healthy
networks:
- dotnet-network
networks:
dotnet-network:
external: false
首先調整一下程式:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
如果直接運行的話,web訪問/healthz節點,那麼可以頁面將直接返回Healthy。看上去沒有問題,那我們按照要求調整一下Dockerfile
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
ENTRYPOINT ["dotnet", "TestWeb.dll"]
然後調整docker-compose.yml文件,讓postgres啟動依賴dotnet-service:
version: '3.7'
services:
postgres:
container_name: postgres-container
image: postgres:13
volumes:
- ./postgres_data:/var/lib/postgresql/data/pgdata
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: "123456"
PGDATA: "/var/lib/postgresql/data/pgdata"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
depends_on:
dotnet-service:
condition: service_healthy
networks:
- dotnet-network
dotnet-service:
image: dotnet-service:latest
container_name: dotnet-service-container
ports:
- 5000:5000
build:
context: ./TestWeb/
dockerfile: ./TestWeb/Dockerfile
environment:
# - ASPNETCORE_ENVIRONMENT=Docker
- ASPNETCORE_URLS=http://*:5000
- App__SelfUrl=http://*:5000
restart: on-failure
networks:
- dotnet-network
networks:
dotnet-network:
external: false
然後postgres就啟動不了了,提示容器unhealthy。運行docker ps,發現.net容器的後面有一個unhealthy。但是程式訪問正常,說明只是沒有正確運行這段話而已。
Dockerfile方案
文檔說.NET 6的鏡像裡面不帶curl這個工具了,需要手動裝一下:
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
RUN apt-get update && apt-get install -y curl
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
ENTRYPOINT ["dotnet", "TestWeb.dll"]
這樣再看,就完全沒問題了,如果把aspnet:6.0改成aspnet:6.0-alpine,空間更節省了(預設是239M,alpine版是108M),還自帶了wget,也沒必要這麼麻煩先安裝curl(比較費時間按)。
HEALTHCHECK CMD wget --spider http://localhost:5000/healthz || exit
docker-compose方案
我不太喜歡去改Dockerfile,而是更傾向於修改docker-compose.yml文件。當然,沒有curl依然還是得在Dockerfile中添加相應語句安裝,但是可以刪除HEALTHCHECK這一條了,直接在docker-compose.yml中對應服務下麵添加:
healthcheck:
test: ["CMD-SHELL", "wget --spider http://localhost:5000/healthz || exit"]
interval: 10s
timeout: 5s
retries: 5
程式依然可以正常運行。
除非特殊說明,本作品由podolski創作,採用知識共用署名 4.0 國際許可協議進行許可。歡迎轉載,轉載請保留原文鏈接~喜歡的觀眾老爺們可以點下關註或者推薦~P.S. 如果程式沒有使用AddHealthChecks,那麼也可以使用暴力一點的,直接用HEALTHCHECK CMD curl --fail http://localhost:5000 || exit,只要能夠正常訪問頁面,就認為是Healthy,不過肯定就少了很多高級特性了。