$ aoox

DocsApplications

Deploy & rollback

What happens when you press Deploy, how to read the logs, health checks and blue/green, and rolling back to a previous version.

Triggers
Deploy button, push webhook, auto-update, Rollback
Runs on
The host's Docker daemon (or a remote server)
Guarantee
A failed build never touches the running container

Life of a deployment

  1. 01queueddeployment created
  2. 02buildingclone + build image
  3. 03pushingpush to registry
  4. 04startingnew container, wait for healthy
  5. 05successold container replaced

Any stage can end in failed; a deployment always ends up as success or failed, never stuck in between. Logs for every stage stream to the Deploy tab in realtime.

  • A deploy is rejected (409) while another deployment for the same application is still active. A webhook arriving in the meantime gets busy back and is not queued.
  • Changing application settings (name, env, domains, resource limits, health check, previews, and so on) while a deploy runs is not lost: the change is saved and takes effect on the next deploy, because the container being created uses the values from when the deploy started. Only the host port and the secret source are rejected (409) while a deploy is active.
  • Failing during building or pushing never touches the currently running container, and doesn't change the application's status.
  • On a remote server the pushing stage is skipped — the image stays on that server's daemon.

Deploy mode: container or service

container (default)service (Swarm)
What gets createdA single container on the app's host/serverA service with N replicas, tasks spread by the scheduler
Version changesBlue/green or replaceRolling update by the daemon (parallelism, delay, order)
FailureThe old container keeps servingAutomatic rollback to the previous spec after a timeout
Stop / StartContainer is stopped/startedScaled to 0 and back to the replica count
MetricsThat containerSum of local tasks only

Service mode needs Docker Swarm active. Changing mode, replica count, placement, or resource limits runs as a config deployment — no build, and the same deployment queue still applies.

Auto-update (image-based applications)

Applications whose source is an image (not a Git repo) can update themselves: a watcher compares the used tag's manifest digest via the registry API every 60 minutes (configurable per application), and creates an auto-update deployment as soon as the digest changes.

  • The baseline comes from the digest recorded at the last pull — not from the tag, so even latest is detected.
  • Supports Docker Hub/GHCR (token flow) and your own registry (basic auth via external registry credentials).
  • The check now button on the application page forces a check without waiting for the interval.

Realtime logs

LogContentsSource
Deployment logClone, build, push, and start output for one deployment. Kept permanently in history.Runner → Socket.IO /logs
Container logstdout/stderr of the running application (follow).docker logs --follow

Resolved Git tokens and database passwords are automatically redacted from both logs and from error messages. Every container aoox creates uses log rotation (json-file with a size and file-count limit), so container logs never fill up the disk.

Health check

Set a Health check path (e.g. /health) in Settings. The container is created with a Docker HEALTHCHECK that calls 127.0.0.1:<container port><path> every 3 seconds, up to 30 times (± 90 seconds).

A sufficient endpoint
GET /health → 200 OK
# no body needed; a fast 2xx status is all that matters
Prerequisite in the image
The health check command tries wget → curl → node -e fetch → python3. An image with none of these (e.g. scratch, distroless) makes the deployment fail with a message naming it. A container that later becomes unhealthy is automatically dropped by Traefik (404).

Blue/green

Kicks in automatically when an application has a domain, no host port, and isn't a preview. The goal: no request ever fails during a version switch.

TimeOld container-next containerNotes
0 sserving—Deploy starts; the new image is already in the registry.
+1 sservingstartingThe <app>-next container is created with the same Traefik labels.
+3–90 sservinghealthyTraefik starts routing to both once -next is healthy.
+3 sremovedservingWait for the proxy to settle, then remove the old one.
done— → <app>-next is renamed to the original name. Deployment succeeds.
ConditionBehavior
Domain, no host port, has a health checkBlue/green as above.
Has a host portPlain replace — two containers can't bind the same port. The health check still decides success/failure.
No health check pathPlain replace; the deployment succeeds as soon as the container starts.
Failure/timeout during blue/green-next is removed, the old container keeps serving, the deployment is failed.
Both temporary containers share the same volume. Applications that lock files (e.g. SQLite without WAL) are better off with a host port or no health check, so plain replace is used instead.

Rollback

  1. Pick a deployment with status success

    In the deployment list (Deploy tab), click Rollback on the target version.

  2. A new rollback-type deployment is created

    No build/push — the old image is pulled from the registry (or whatever's still on the remote server) and the container is replaced through the same path: health check, blue/green.

  • Rollback uses the old image but the current env — handy for fixing a bad env without rebuilding.
  • An image tag already deleted from the Registry can't be a rollback target.

Stop & start

The Stop/Start buttons on the Deploy tab stop/run the container without rebuilding. Container-down notifications aren't sent for an intentional stop.

What change triggers what

What changedEffectNeeds
Code in the repoNew imageDeploy (or push + webhook)
Image tag changes (image source)Pull a new imageAutomatic if auto-update is on
Build args, Dockerfile path, build methodNew imageDeploy
Environment variablesApplied when the container is createdDeploy or Rollback
Domain, mount, resource limit (removed)Container recreated from the current imageAutomatic, no build
Deploy mode, replicas, placementService updated (rolling)Config deployment, automatic
Resource limit (changed value)Applied immediatelyNothing

Next steps

Found a mistake? Edit this page on GitHub ↗