Skip to main content

Updating Services

Learn how to update running services with zero downtime, rollback changes, and handle different update scenarios.

Basic Update Workflow

The standard update process is simple:

# Make changes to your code or compose.yaml
vim src/app.py

# Deploy updates
uc deploy

Uncloud automatically:

  1. Rebuilds changed services (if using build)
  2. Creates new containers
  3. Waits for new containers to be healthy
  4. Switches traffic
  5. Removes old containers

Zero downtime guaranteed for services with multiple replicas.

Update Strategies

Rolling Updates (Default)

Uncloud uses rolling updates by default. New containers are created before old ones are removed:

services:
web:
build: .
deploy:
replicas: 3
uc deploy

Update sequence:

  1. Create web-4 (new version)
  2. Wait for web-4 to be healthy
  3. Remove web-1 (old version)
  4. Create web-5
  5. Remove web-2
  6. Create web-6
  7. Remove web-3

Traffic is always served during updates.

Force Recreate

Force recreation of all containers even if configuration hasn't changed:

uc deploy --recreate

When to use:

  • Configuration changed outside of compose.yaml
  • Container is in an unhealthy state
  • You want to pull the latest :latest image

Update Specific Services

Update only changed services:

# Update only web service
uc deploy web

# Update web and API
uc deploy web api

Other services remain untouched.

Code Updates

Update Application Code

# Edit your code
vim src/handler.py

# Deploy the updated code
uc deploy

Uncloud rebuilds the image with your changes and deploys it.

Skip Rebuild

If you've already built the image separately:

# Build image
uc build

# Deploy without rebuilding
uc deploy --no-build

Configuration Updates

Update Environment Variables

Change environment variables in compose.yaml:

services:
web:
image: myapp:latest
environment:
LOG_LEVEL: debug # Changed from 'info'
NEW_FEATURE: enabled # Added new variable
uc deploy

Containers are recreated with new environment variables.

Update Resource Limits

services:
web:
image: myapp:latest
deploy:
resources:
limits:
cpus: '2' # Increased from '1'
memory: 2G # Increased from 1G
uc deploy

Update Ports

services:
web:
image: myapp:latest
x-ports:
- app.example.com:8000/https
- www.app.example.com:8000/https # Added new domain
uc deploy

Caddy configuration is updated automatically.

Scaling Updates

Scale Replicas

Increase or decrease the number of replicas:

services:
web:
image: myapp:latest
deploy:
replicas: 5 # Scaled from 3
uc deploy

Or use the dedicated scale command:

uc scale web 5

Scale Down

Reduce replicas:

uc scale web 1

Excess containers are removed gracefully.

Image Updates

Update Image Version

Change the image tag in compose.yaml:

services:
web:
image: myapp:v1.2.4 # Updated from v1.2.3
uc deploy

Update from Registry

For pre-built images, ensure new version is pulled:

uc deploy --pull

Forces pulling the latest image from the registry even if a local version exists.

Rollback Strategies

Rollback to Previous Version

If you need to rollback:

Option 1: Change image tag

services:
web:
image: myapp:v1.2.3 # Back to previous version
uc deploy

Option 2: Revert code and rebuild

# Revert to previous commit
git revert HEAD

# Rebuild and deploy
uc deploy

Option 3: Deploy old image directly

# List services to see old images
uc ps

# Update compose.yaml to use old image tag
# Then deploy
uc deploy

Keep Previous Images

Tag images with versions for easy rollback:

services:
web:
build: .
image: myapp:${VERSION:-latest}
# Deploy version 1.2.4
VERSION=v1.2.4 uc deploy

# Rollback to 1.2.3
VERSION=v1.2.3 uc deploy

Health Checks and Updates

Define Health Checks

Add health checks to ensure safe updates:

services:
web:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s

During updates, Uncloud waits for health checks to pass before switching traffic.

Update with Health Check Failures

If new containers fail health checks:

  1. Old containers keep running
  2. New containers are marked unhealthy
  3. Traffic stays on old containers
  4. Check logs: docker logs <container-id>
  5. Fix the issue and redeploy

Volume Updates

Update Volume Mounts

Add or change volume mounts:

services:
web:
image: myapp:latest
volumes:
- ./data:/app/data
- ./logs:/app/logs # Added new volume
uc deploy

Note: Containers are recreated when volumes change.

Persistent Data

Data in named volumes persists across updates:

services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data

volumes:
db-data: # Data survives container updates

Updating the db service doesn't affect data in db-data volume.

Compose File Updates

Update compose.yaml Structure

You can freely update your compose.yaml:

  • Add new services
  • Remove services
  • Rename services (creates new service, old one stays)
  • Change service dependencies
services:
web:
image: myapp:latest

# Added new service
worker:
image: myapp:latest
command: python -m celery worker
uc deploy

New services are created, existing services are updated if changed.

Remove Services

To remove a service, delete it from compose.yaml and use uc rm:

# Remove from compose.yaml
# Then remove from cluster
uc rm old-service

Update Automation

Automated Updates

For production deployments:

# Non-interactive deployment
uc deploy --yes

Or set environment variable:

export UNCLOUD_AUTO_CONFIRM=true
uc deploy

Pre-deployment Checks

Preview changes before applying:

# Shows deployment plan without executing
uc deploy
# Review the plan
# Type 'yes' to proceed or 'no' to cancel

Multi-service Updates

Update All Services

# Make changes to multiple services
vim frontend/src/app.js
vim api/src/handler.py

# Deploy all changes
uc deploy

Both services are rebuilt and updated.

Sequential Updates

Update services one at a time:

# Update database first
uc deploy db

# Then update API
uc deploy api

# Finally update frontend
uc deploy frontend

Dependency-aware Updates

Update with dependencies:

# Update API and all its dependencies
uc deploy api --deps

Troubleshooting Updates

Update Stuck or Slow

If updates seem slow:

  1. Check build progress (if building)
  2. Check image push progress
  3. Check container health: docker ps
  4. Review logs: docker logs <container-id>

Containers Not Starting

Check container logs:

# List containers
uc ps

# View logs
docker logs <container-id>

Common issues:

  • Port conflicts
  • Missing environment variables
  • Configuration errors
  • Failed health checks

Old Containers Still Running

Verify the deployment completed:

uc ps

Look for containers with old image tags or older creation times.

Force cleanup:

uc deploy --recreate

Changes Not Reflected

Ensure you're rebuilding:

# Force rebuild without cache
uc build --no-cache

# Deploy
uc deploy

Or combine:

uc deploy --no-cache

Best Practices

  1. Tag images with versions for easy rollback
  2. Use health checks to ensure safe updates
  3. Test in staging before production updates
  4. Keep old images for quick rollback
  5. Update one service at a time for complex apps
  6. Monitor logs during updates
  7. Use replicas > 1 for zero-downtime updates

Next Steps