前回はシンプルなデプロイ方法を紹介しました。今回は、Docker Compose を使用してアプリケーションのヘルスチェックを設定する方法について解説します。
Docker Compose でヘルスチェックを設定するには、主に以下の3つのファイルを修正します。
`test` で指定したコマンドが成功(ステータスコード 0)を返すと、コンテナは「正常」と判断されます。この例では、`curl` を使用してアプリケーションの `/health/status` エンドポイントにリクエストを送信し、応答があるかを確認しています。
`RUN apt-get update && apt-get install -y curl` という行が `curl` をインストールする部分です。これにより、コンテナ内でヘルスチェックコマンドを実行できるようになります。
このコードでは、`AddHealthChecks()` を使用してカスタムチェック "api-ready" を登録し、`UseHealthChecks()` を使用して `/health/status` と `/health/ready` という2つのエンドポイントを公開しています。これにより、Docker Compose がヘルスチェックを実行できるようになります。
1. docker-compose.override.yml の設定
このファイルは、docker-compose.yml の設定をオーバーライドするために使用されます。ここで `healthcheck` セクションを追加し、コンテナの健全性を確認するコマンドとタイミングを定義します。version: '3.4'
services:
myapi:
env_file: .env
environment:
- ASPNETCORE_ENVIRONMENT=Development
- API_PORT=8080
- APP_NAME=${APP_NAME}
ports:
- "9000:8080"
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health/status"]
interval: 30s
timeout: 1m
retries: 3
start_period: 40s
2. Dockerfile の修正
上記の `docker-compose.override.yml` では `curl` コマンドを使用していますが、標準の .NET Core コンテナには `curl` が含まれていないため、Dockerfile に `curl` をインストールするコマンドを追加する必要があります。#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
COPY . /app
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
ENTRYPOINT ["dotnet", "MyApp.dll"]
RUN apt-get update && apt-get install -y curl
3. .NET Core アプリケーションのヘルスチェック実装
最後に、.NET Core アプリケーション側でヘルスチェックのエンドポイントを設定します。以下は `Program.cs` の例です。using Microsoft.Extensions.Diagnostics.HealthChecks;
using MyApp;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using HealthChecks.UI.Client;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureAppConfiguration(config =>
{
config.AddEnvironmentVariables();
});
// サービスの登録
builder.Services.Configure<AppConfig>(builder.Configuration);
builder.Services.AddControllers();
builder.Services.AddHealthChecks().AddCheck("api-ready", check => HealthCheckResult.Healthy(),
tags: new string[] {
"api-ready"
});
builder.Services.AddHealthChecksUI().AddInMemoryStorage();
// Swagger の設定
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// HTTP リクエストパイプラインの設定
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//app.UseHttpsRedirection();
app.UseHealthChecksUI(setup: setup =>
{
setup.UIPath = "/health";
});
app.UseHealthChecks("/health/status", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.UseHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = x => x.Name.Contains("api-ready")
});
app.UseAuthorization();
app.MapControllers();
app.Run();