Rolling deployments
How uc deploy updates your services without downtime and automatically rolls back on failure.
Uncloud uses a rolling deployment to update your service by replacing its containers one at a time. Before moving on to the next container, Uncloud waits for the new one to pass health monitoring. If it fails to become healthy, Uncloud stops the deployment and rolls back that container to the old one. This keeps your service available throughout the update.
For a service with three replicas and the default start-first update order, the deployment looks like
this:
- Start new container #1, wait until healthy
- Stop and remove old container #1
- Start new container #2, wait until healthy
- Stop and remove old container #2
- Start new container #3, wait until healthy
- Stop and remove old container #3
At every step, at least three containers are serving traffic.
Update order
The update order controls whether Uncloud starts the new container before or after stopping the old one.
| Order | What happens | Best for |
|---|---|---|
start-first | Start new container, then stop old (running containers briefly overlap) | Stateless services (web apps, APIs) |
stop-first | Stop old container, then start new | Stateful services (databases) |
The default is start-first so there's no downtime. But it automatically switches to stop-first in two cases:
- Host port conflicts: the old container must free the port before the new one can bind to it.
- Single-replica service with a volume: two containers simultaneously writing to the same volume can corrupt data, so Uncloud stops the old container first to prevent this.
stop-first can cause a brief downtime while the old container stops and the new one starts in these cases. The
deployment plan printed by uc deploy indicates which containers will be replaced with stop-first.
A multiple-replica service with a volume doesn't automatically switch to stop-first as Uncloud assumes that the
concurrent access is desired and safe. Host path and tmpfs mounts don't trigger the switch either.
Override update order
You can override the update order with deploy.update_config.order:
services:
app:
image: myapp
volumes:
- data:/data
deploy:
update_config:
order: start-first
volumes:
data:
This single-replica service uses a volume, so Uncloud would normally use stop-first. Setting order: start-first
overrides that.
This is useful if your app handles concurrent access to data safely and you want to avoid downtime. For example, the app uses an SQLite database in WAL mode on the volume.
Health monitoring
After starting each new container, Uncloud monitors it for failures for 5 seconds to make sure it keeps running and not crashing. If it keeps restarting after this period, the deployment fails and Uncloud rolls back that container to the old one.
This is a safeguard to prevent you from deploying broken code or misconfiguration that would cause downtime. 5 seconds is typically enough for a process in a container to initialise all its dependencies and start.
You can change the monitoring period for a service with deploy.update_config.monitor. For example, increase it if your
app takes longer to start or if you want to give it more time to recover from transient errors on startup.
Set it to 0s to skip monitoring entirely if you are confident the new containers will start correctly and want to
speed up the deployment.
services:
app:
image: myapp
deploy:
update_config:
# Specified as duration: 500ms, 20s, 1m30s, 0s (skip)
monitor: 10s
You can also change the default monitoring period (5s) for all services globally with an environment variable
UNCLOUD_HEALTH_MONITOR_PERIOD:
export UNCLOUD_HEALTH_MONITOR_PERIOD=10s
# or skip monitoring for all services
export UNCLOUD_HEALTH_MONITOR_PERIOD=0s
deploy.update_config.monitor overrides the global default for each service.
Health checks
If your container has a healthcheck
configured, Uncloud also checks its health status during and after the monitoring period.
If the container becomes healthy before the monitoring period ends, the deployment succeeds early and moves on to the
next container. If the container is unhealthy after the monitoring period, Uncloud
rolls it back and fails the deployment. Transient unhealthy states during the monitoring
period are tolerated to give the container time to recover from startup issues.
To make deployments safer and faster, it's recommended to configure a health check that can quickly notify
Uncloud when containers start successfully and become ready to serve traffic. You can configure it with
healthcheck in your Compose file or
HEALTHCHECK in your image Dockerfile:
services:
app:
image: myapp
healthcheck:
test: curl -f http://localhost:8000/health
interval: 5s
retries: 3
start_period: 10s
start_interval: 1s
If a health check fails after the deployment, Uncloud automatically removes the unhealthy container from the Caddy configuration to prevent routing traffic to that container. But it doesn't automatically restart or roll it back.
Uncloud automatically adds it back to Caddy when it recovers and becomes healthy again. You can inspect the health
status of your containers with uc ps or
uc inspect and check their logs with
uc logs.
Skip health monitoring
To skip health monitoring for faster emergency deployments, use uc deploy --skip-health.
--skip-health won't detect containers that crash on startup or become unhealthy so won't roll them back or stop the
deployment. Use this only for emergency deployments when you are confident the new containers will start correctly.
Rollback on failure
If a new container fails health monitoring during a deployment, Uncloud stops it but keeps it around so you can inspect
its state and logs. For stop-first order, Uncloud also restarts the old container. The deployment then stops and the
remaining containers are left untouched.
For example, if the first container in a rolling update succeeds but the second one fails, the first replacement stays in place.
Retry after failure
You can retry the deployment by running uc deploy again. Uncloud will skip the successfully deployed containers if the
configuration hasn't changed and only redeploy the remaining ones.
See also
- Deploy an app: Build and deploy from source code or pre-built images
- Compose support matrix: Supported Compose features and Uncloud extensions