Monitor and restart unhealthy docker containers.
This functionality was proposed to be included with the addition of HEALTHCHECK, however didn't make the cut.
This container is a stand-in till there is native support for --exit-on-unhealthy moby/moby#22719.
Maintained fork of willfarrell/docker-autoheal by VSK Studio. The upstream image stays on an end-of-life Alpine base and its pull requests are no longer reviewed. This fork keeps the base on the latest Alpine release, rebuilds every night to pick up security fixes, and carries the upstream fixes worth having.
ghcr.io/vskstudio/autoheal
Platforms: linux/amd64, linux/arm64.
| Tag | Built from | Rebuilt |
|---|---|---|
latest |
main |
on every push to main and every night |
1.4.0, 1.4, 1 |
v1.4.0 |
on release |
sha-<commit> |
the matching commit | once |
Pin a version tag (or a sha-* tag) in production. Use latest to follow the nightly rebuilds.
- Alpine 3.24 base (upstream: 3.18, end of life). The CA bundle no longer trusts the distrusted emSign/eMudhra intermediates.
- SIGTERM handler kills the sleep child instead of re-signalling itself, so the container stops cleanly (upstream #131).
- Refuses to start when the Docker unix socket exists but is not writable (upstream #146, rewritten in POSIX sh).
autoheal=falseopts a container out regardless of case; upstream only honouredFalse(upstream #153).- Paused containers are left alone (upstream #98).
- A Docker API error or an unreachable socket is logged and retried on the next interval instead of crashing the loop with a
jqerror (upstream #35). - Webhook payloads are built with
jq, so container names with quotes or backslashes produce valid JSON; failed deliveries are logged, and the startup log says whetherWEBHOOK_URLandAPPRISE_URLare set without printing them (upstream #137). WEBHOOK_JSON_KEYdefaults tocontenteverywhere (upstream #152).tzdatais installed, soTZworks (upstream #143).- Integration tests run in CI before every image is published.
- Image published to GHCR with OCI labels, multi-arch, nightly rebuild.
docker run -d \
--name autoheal \
--restart=always \
-e AUTOHEAL_CONTAINER_LABEL=all \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/vskstudio/autoheal:1docker run -d \
--name autoheal \
--restart=always \
-e AUTOHEAL_CONTAINER_LABEL=all \
-e DOCKER_SOCK=tcp://$HOST:$PORT \
-v /path/to/certs/:/certs/:ro \
ghcr.io/vskstudio/autoheal:1docker run -d \
--name autoheal \
--restart=always \
--tlscacert=/certs/ca.pem \
--tlscert=/certs/client-cert.pem \
--tlskey=/certs/client-key.pem \
-e AUTOHEAL_CONTAINER_LABEL=all \
-e DOCKER_HOST=tcp://$HOST:2376 \
-e DOCKER_SOCK=tcps://$HOST:2376 \
-e DOCKER_TLS_VERIFY=1 \
-v /path/to/certs/:/certs/:ro \
ghcr.io/vskstudio/autoheal:1The certificates and keys need these names and resides under /certs inside the container:
- ca.pem
- client-cert.pem
- client-key.pem
See https://docs.docker.com/engine/security/https/ for how to configure TCP with mTLS
Set TZ, or map the host's /etc/localtime into the container.
docker run ... -e TZ=Europe/Paris
docker run ... -v /etc/localtime:/etc/localtime:roChoose one of the three alternatives:
a) Apply the label autoheal=true to your container to have it watched;
b) Set ENV AUTOHEAL_CONTAINER_LABEL=all to watch all running containers;
c) Set ENV AUTOHEAL_CONTAINER_LABEL to existing container label that has the value true;
Note: You must apply
HEALTHCHECKto your docker images first.
Note: A container labelledautoheal=falseis never restarted, which is how you exclude one when usingAUTOHEAL_CONTAINER_LABEL=all. Paused containers are never restarted either.
Note: In Compose, quote label values (autoheal: "true"), YAML would otherwise turn them into booleans.
See https://docs.docker.com/engine/reference/builder/#healthcheck for details.
services:
app:
extends:
file: ${PWD}/services.yml
service: app
labels:
autoheal-app: true
autoheal:
deploy:
replicas: 1
environment:
AUTOHEAL_CONTAINER_LABEL: autoheal-app
image: ghcr.io/vskstudio/autoheal:1
network_mode: none
restart: always
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sockautoheal.stop.timeout=20 |
Per containers override for stop timeout seconds during restart |
|---|
| Variable | Description |
|---|---|
AUTOHEAL_CONTAINER_LABEL=autoheal |
set to existing label name that has the value true |
AUTOHEAL_INTERVAL=5 |
check every 5 seconds |
AUTOHEAL_START_PERIOD=0 |
wait 0 seconds before first health check |
AUTOHEAL_DEFAULT_STOP_TIMEOUT=10 |
Docker waits max 10 seconds (the Docker default) for a container to stop before killing during restarts (container overridable via label, see below) |
AUTOHEAL_ONLY_MONITOR_RUNNING=false |
All containers monitored by default. Set this to true to only monitor running containers. This will result in paused containers being ignored. |
DOCKER_SOCK=/var/run/docker.sock |
Unix socket for curl requests to Docker API |
CURL_TIMEOUT=30 |
--max-time seconds for curl requests to Docker API |
WEBHOOK_URL="" |
post message to the webhook if a container was restarted (or restart failed) |
WEBHOOK_JSON_KEY=content |
JSON key holding the message in the webhook payload (content suits Discord, text suits Slack) |
APPRISE_URL="" |
post {"title":"Autoheal","body":...} to an Apprise API endpoint |
POST_RESTART_SCRIPT="" |
script run after each restart, with the container name, short id, state and timeout as arguments |
docker buildx build -t autoheal .
docker run -d \
-e AUTOHEAL_CONTAINER_LABEL=all \
-v /var/run/docker.sock:/var/run/docker.sock \
autohealPush a semver tag; the workflow publishes X.Y.Z, X.Y and X:
git tag v1.4.1
git push origin v1.4.1