• ASP.NET CORE在docker中的健康检查(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,不过肯定就少了很多高级特性了。

  • 相关阅读:
    微软出品自动化神器【Playwright+Java】系列(九)多线程、重定向、弹出新窗口、截图、新页面、录制、页面对象模式操作
    A Mathematical Framework for Transformer Circuits—(二)
    如何用JavaScripte和HTML 实现一整套的考试答题卡和成绩表
    几种swf格式视频转换器简介
    theos tweak导入自定义类
    阶段七-Day01-SpringMVC
    You can’t specify target table ‘xxx’ for update in FROM clause
    iOS小技能:安全措施
    WebKitX ActiveX 5.0.0.15221 Crack
    Python中if __name__ == ‘__main__‘,__init__和self 的解析
  • 原文地址:https://www.cnblogs.com/podolski/p/16603177.html