Backup & Rollback
Automatic image backup before updates and one-click rollback to any previous version.
How It Works
Before every container update, drydock automatically backs up the current image metadata including the image name, tag, digest, and timestamp. This ensures you always have a record of exactly which image was running prior to each update.
These image-restore backup records live in the SQLite store in v1.8.0-rc.1 builds; v1.7 and earlier use the LokiJS JSON store. The /store volume persists them in either case. They describe container images, rather than snapshots of Drydock's database. Each container retains its N most recent backups, with older entries pruned automatically when the limit is exceeded.
Backup Retention
The number of backups retained per container is configurable via a trigger environment variable.
| Env var | Required | Description | Supported values | Default value when missing |
|---|---|---|---|---|
DD_ACTION_DOCKER_{trigger_name}_BACKUPCOUNT | ⚪ | Number of backups to retain per container | integer | 3 |
DD_ACTION_DOCKERCOMPOSE_{trigger_name}_BACKUPCOUNT | ⚪ | Number of backups to retain per container | integer | 3 |
Manual Rollback
Rollback is available in two ways:
- UI -- on the container detail page, select a previous backup and click Rollback. A shortcut is also available directly from the container's actions menu (the
...menu on each row). - API -- send a
POSTrequest to/api/v1/containers/:id/rollback, where:idis the container ID.
Rollback uses a stop-remove-recreate strategy: drydock stops the current container, removes it, and creates a new container with the original name using the backup image. The image is pulled and created from an immutable repo:tag@sha256:... reference whenever a digest can be established, so a registry retag between the backup and the rollback can't change what gets deployed. Backups written before digest capture existed resolve one from the retained local image at rollback time; if none can be established and the security policy requires one, the rollback is refused with an error instead of deploying the mutable tag.
You can optionally pass a backupId in the request body to target a specific backup. If omitted, the most recent backup is used.
# Roll back to the most recent backup
curl -X POST http://localhost:3000/api/v1/containers/my-container-id/rollback \
-H 'X-DD-Confirm-Action: container-rollback'
# Roll back to a specific backup
curl -X POST http://localhost:3000/api/v1/containers/my-container-id/rollback \
-H 'X-DD-Confirm-Action: container-rollback' \
-H "Content-Type: application/json" \
-d '{"backupId": "abc123"}'Health-gate SSE heartbeat
During an update, drydock waits for the new container to pass its Docker HEALTHCHECK. While waiting, periodic heartbeat events keep the UI informed so real-time status stays accurate even when healthcheck intervals are long (e.g. 60 s).
| Env var | Required | Description | Default |
|---|---|---|---|
DD_UPDATE_HEALTH_GATE_HEARTBEAT_MS | ⚪ | Interval (ms) at which phase: 'health-gate' SSE events are re-emitted during the health-gate wait. Set to 0 to disable. Values below 1000 fail startup. | 10000 |
Auto-Rollback on Health Failure
Containers with a Docker HEALTHCHECK can automatically roll back if they become unhealthy after an update.
Container Labels
| Label | Type | Default | Description |
|---|---|---|---|
dd.rollback.auto | boolean | false | Enable auto-rollback when health check fails after update |
dd.rollback.window | number (ms) | 300000 | Duration to monitor health after update (5 minutes) |
dd.rollback.interval | number (ms) | 10000 | Frequency of health status checks (10 seconds) |
How It Works
- An update completes successfully
- If
dd.rollback.auto=trueand the container has aHEALTHCHECK, monitoring starts - Health status is polled every
dd.rollback.intervalfor the duration ofdd.rollback.window - If the status becomes
unhealthy, rollback is triggered automatically - If the window expires without failure, the container is considered stable
HEALTHCHECK instruction in your Dockerfile. Without one, monitoring is skipped.Examples
services:
myapp:
image: myapp:latest
labels:
- dd.rollback.auto=true
- dd.rollback.window=600000
- dd.rollback.interval=5000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3