wiki: add SELinux AVC chart, enriched alerts, new server setup, and pending articles; update indexes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
157
02-selfhosting/docker/docker-healthchecks.md
Normal file
157
02-selfhosting/docker/docker-healthchecks.md
Normal file
@@ -0,0 +1,157 @@
|
||||
---
|
||||
title: "Docker Healthchecks"
|
||||
domain: selfhosting
|
||||
category: docker
|
||||
tags: [docker, healthcheck, monitoring, uptime-kuma, compose]
|
||||
status: published
|
||||
created: 2026-03-23
|
||||
updated: 2026-03-23
|
||||
---
|
||||
|
||||
# Docker Healthchecks
|
||||
|
||||
A Docker healthcheck tells the daemon (and any monitoring tool) whether a container is actually working — not just running. Without one, a container shows as `Up` even if the app inside is crashed, deadlocked, or waiting on a dependency.
|
||||
|
||||
## Why It Matters
|
||||
|
||||
Tools like Uptime Kuma report containers without healthchecks as:
|
||||
|
||||
> Container has not reported health and is currently running. As it is running, it is considered UP. Consider adding a health check for better service visibility.
|
||||
|
||||
A healthcheck upgrades that to a real `(healthy)` or `(unhealthy)` status, making monitoring meaningful.
|
||||
|
||||
## Basic Syntax (docker-compose)
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `test` | Command to run. Exit 0 = healthy, non-zero = unhealthy. |
|
||||
| `interval` | How often to run the check. |
|
||||
| `timeout` | How long to wait before marking as failed. |
|
||||
| `retries` | Failures before marking `unhealthy`. |
|
||||
| `start_period` | Grace period on startup before failures count. |
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### HTTP service (wget — available in Alpine)
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost:2368/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
```
|
||||
|
||||
### HTTP service (curl)
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
```
|
||||
|
||||
### MySQL / MariaDB
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-psecret"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
```
|
||||
|
||||
### PostgreSQL
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
```
|
||||
|
||||
### Redis
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### TCP port check (no curl/wget available)
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "nc -z localhost 8080 || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
## Using Healthchecks with `depends_on`
|
||||
|
||||
Healthchecks enable proper startup ordering. Instead of a fixed sleep, a dependent container waits until its dependency is actually ready:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
```
|
||||
|
||||
This prevents the classic race condition where the app starts before the database is ready to accept connections.
|
||||
|
||||
## Checking Health Status
|
||||
|
||||
```bash
|
||||
# See health status in container list
|
||||
docker ps
|
||||
|
||||
# Get detailed health info including last check output
|
||||
docker inspect --format='{{json .State.Health}}' <container> | jq
|
||||
```
|
||||
|
||||
## Ghost Example
|
||||
|
||||
Ghost (Alpine-based) uses `wget` rather than `curl`:
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost:2368/ghost/api/v4/admin/site/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
```
|
||||
|
||||
## Gotchas & Notes
|
||||
|
||||
- **Alpine images** don't have `curl` by default — use `wget` or install curl in the image.
|
||||
- **`start_period`** is critical for slow-starting apps (databases, JVM services). Failures during this window don't count toward `retries`.
|
||||
- **`CMD` vs `CMD-SHELL`** — use `CMD` for direct exec (no shell needed), `CMD-SHELL` when you need pipes, `&&`, or shell builtins.
|
||||
- **Uptime Kuma** will pick up Docker healthcheck status automatically when monitoring via the Docker socket — no extra config needed.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[debugging-broken-docker-containers]]
|
||||
- [[netdata-docker-health-alarm-tuning]]
|
||||
Reference in New Issue
Block a user