ASP.NET CORE在docker中的健康检查(healthcheck)

  • ASP.NET CORE在docker中的健康检查(healthcheck)已关闭评论
  • 172 次浏览
  • A+
所属分类:.NET技术
摘要

在使用docker-compose的过程中,很多程序都提供了健康检查(healthcheck)的方法,通过健康检查,应用程序能够在确保其依赖的程序都已经启动的前提下启动,减少各种错误的发生,同时,合理设计的健康检查也能够提供给外界关于应用程序状态的一些信息。

在使用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   

程序依然可以正常运行。

P.S. 如果程序没有使用AddHealthChecks,那么也可以使用暴力一点的,直接用HEALTHCHECK CMD curl --fail http://localhost:5000 || exit,只要能够正常访问页面,就认为是Healthy,不过肯定就少了很多高级特性了。