diff --git a/Controllers/HealthController.cs b/Controllers/HealthController.cs new file mode 100644 index 0000000..e899987 --- /dev/null +++ b/Controllers/HealthController.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2026 Stefan Koelle (https://stefankoelle.de) +// Licensed under the MIT License. See LICENSE file in project root for details. +using FocusApp.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace FocusApp.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class HealthController : ControllerBase +{ + private readonly FocusContext _context; + private readonly ILogger _logger; + + public HealthController(FocusContext context, ILogger logger) + { + _context = context; + _logger = logger; + } + + [HttpGet] + public async Task GetHealth() + { + var health = new + { + status = "healthy", + database = "unknown", + timestamp = DateTime.UtcNow, + version = "2.0.0" + }; + + try + { + await _context.Database.CanConnectAsync(); + health = new + { + status = "healthy", + database = "connected", + timestamp = DateTime.UtcNow, + version = "2.0.0" + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Health check failed"); + health = new + { + status = "unhealthy", + database = "disconnected", + timestamp = DateTime.UtcNow, + version = "2.0.0" + }; + return StatusCode(503, health); + } + + return Ok(health); + } +} diff --git a/Dockerfile b/Dockerfile index 2e78622..1bf917a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ RUN dotnet publish FocusApp.csproj -c Release -o /app/publish --no-restore -p:Sk # Stage 3: Runtime FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=build /app/publish . COPY LICENSE . diff --git a/README.md b/README.md index 6999974..64ac097 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,42 @@ Content-Type: application/json [1, 3, 2, 4] ``` +### Health Check +```http +GET /api/health +``` + +Response (200 OK): +```json +{ + "status": "healthy", + "database": "connected", + "timestamp": "2026-08-09T12:00:00Z", + "version": "2.0.0" +} +``` + +Response (503 Service Unavailable): +```json +{ + "status": "unhealthy", + "database": "disconnected", + "timestamp": "2026-08-09T12:00:00Z", + "version": "2.0.0" +} +``` + +**Uptime Kuma Konfiguration:** +- URL: `http://localhost:5000/api/health` +- Methode: GET +- Erwarteter Status: 200 +- Intervall: 60 Sekunden + +**Docker Healthcheck:** +- Automatisch in `docker-compose.yml` konfiguriert +- Prüft alle 30 Sekunden den Health Endpoint +- Container wird als `healthy`/`unhealthy` markiert + ## 🎯 Entwicklung ### Backend (Development) diff --git a/docker-compose.yml b/docker-compose.yml index 72d965e..ff015c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,3 +13,9 @@ services: - DB_NAME=${DB_NAME} - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s