feat: add docker healthcheck to dokku container

The official dokku/dokku image gains a HEALTHCHECK directive backed by a loopback-only HTTP endpoint at `127.0.0.1:18080/_dokku/health`. The endpoint reports 200 once first-boot bootstrap finishes, sshd and nginx are accepting connections, and `dokku ps:restore` completes; otherwise it returns 503. Changes are scoped to the Docker overlay and Dockerfile so debian-package installs are unaffected.
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-10 21:17:09 -04:00
parent a553f04966
commit cc0843391f
5 changed files with 60 additions and 3 deletions

View File

@@ -81,3 +81,6 @@ RUN \
&& rm -f /usr/local/openresty/nginx/conf/sites-enabled/default /usr/share/openresty/html/index.html \
&& sed -i '/imklog/d' /etc/rsyslog.conf \
&& rm -f /var/log/btmp /var/log/wtmp /var/log/*log /var/log/apt/* /var/log/dokku/*.log /var/log/nginx/* /var/log/openresty/*
HEALTHCHECK --interval=30s --timeout=10s --start-period=5m --retries=3 \
CMD curl -fsS http://127.0.0.1:18080/_dokku/health || exit 1

View File

@@ -35,6 +35,9 @@ main() {
support-userns
rm -f /var/run/dokku/ready
mkdir -p /var/run/dokku
if [[ ! -d /mnt/dokku ]]; then
log-info "Creating missing /mnt/dokku"
mkdir -p /mnt/dokku

View File

@@ -0,0 +1,16 @@
# Internal health endpoint for the official dokku/dokku Docker image.
# Bound to loopback so it is reachable only from inside the container
# and never conflicts with user app vhosts on 80/443.
server {
listen 127.0.0.1:18080;
server_name _;
access_log off;
default_type text/plain;
location = /_dokku/health {
if (-f /var/run/dokku/ready) {
return 200 "ok\n";
}
return 503 "not ready\n";
}
}

View File

@@ -10,6 +10,10 @@ if [[ "$1" -ne 0 ]]; then
fi
echo "Done restoring dokku apps."
exec sleep infinity
exit 0
while ! (echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1; do sleep 1; done
while ! (echo > /dev/tcp/127.0.0.1/80) >/dev/null 2>&1; do sleep 1; done
touch /var/run/dokku/ready
echo "Dokku is ready."
exec sleep infinity

View File

@@ -44,7 +44,38 @@ services:
restart: unless-stopped
```
The above command will start a new docker container that is ready when a message similar to `Runit started as PID 12345` appears.
## Container readiness
The image ships with a Docker `HEALTHCHECK` that flips from `starting` to `healthy` once first-boot bootstrap is complete (skel restored, `plugin-list` plugins installed, core install triggers fired), nginx and sshd are accepting connections, and `dokku ps:restore` has finished. Until those conditions hold, the container is considered unhealthy and dependent services should not yet send traffic.
To check the current state from the host:
```shell
docker inspect --format='{{.State.Health.Status}}' dokku
```
Internally, the check is backed by a loopback-only HTTP endpoint:
```shell
docker exec dokku curl -fsS http://127.0.0.1:18080/_dokku/health
```
The endpoint binds to `127.0.0.1:18080` inside the container by design - it is not published to the host and does not interfere with user app vhosts on ports 80/443.
Compose dependents can gate on the healthcheck via `depends_on` with `condition: service_healthy`:
```yaml
services:
dokku:
image: dokku/dokku:0.38.2
# ...
bootstrap:
image: alpine:3.20
command: ["echo", "dokku is ready"]
depends_on:
dokku:
condition: service_healthy
```
Dokku is run in the following configuration: