Skip to main content

Deploy Pre-built Images

Deploy applications using pre-built images from Docker Hub, GitHub Container Registry, or private registries. Skip the build step entirely.

When to Use Pre-built Images

  • Deploying public applications (nginx, PostgreSQL, Redis)
  • Using images built in CI/CD pipelines
  • Deploying third-party services
  • Images built externally or by another team

Public Images from Docker Hub

Single Service

Deploy a simple web server:

services:
web:
image: nginx:alpine
x-ports:
- www.example.com:80/https
uc deploy

That's it! No build step needed. Uncloud pulls the image directly from Docker Hub to your cluster machines.

Multiple Public Services

Deploy a complete application stack:

services:
web:
image: nginx:alpine
x-ports:
- www.example.com:80/https
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro

db:
image: postgres:16-alpine
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: ${DB_PASSWORD}

redis:
image: redis:7-alpine
volumes:
- redis-data:/data

volumes:
db-data:
redis-data:
uc deploy

Images from Other Registries

GitHub Container Registry

Use images from GitHub:

services:
app:
image: ghcr.io/username/myapp:v1.2.3
x-ports:
- app.example.com:8000/https

Docker Hub with Username

Specify Docker Hub username explicitly:

services:
app:
image: username/myapp:latest

Custom Registry

Use any Docker registry:

services:
app:
image: registry.example.com/myapp:v2.0.0

Private Registries

Authenticate with Registry

Configure Docker authentication on your local machine:

# Docker Hub
docker login

# GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u username --password-stdin

# Custom registry
docker login registry.example.com

Uncloud uses your local Docker credentials when pulling images.

Deploy from Private Registry

services:
app:
image: registry.example.com/private/myapp:latest
x-ports:
- app.example.com:8000/https
uc deploy

Note: Cluster machines must have access to the private registry. You can configure Docker credentials on each machine or use registry tokens.

Specific Image Versions

Semantic Versioning

Pin to specific versions for production:

services:
app:
image: myapp:1.2.3 # Specific version

db:
image: postgres:16.2-alpine # Specific minor version

redis:
image: redis:7-alpine # Major version with auto-updates

Tags and Digests

Use SHA256 digests for immutable deployments:

services:
app:
image: myapp@sha256:abcd1234... # Immutable reference

Get image digest:

docker pull myapp:1.2.3
docker inspect myapp:1.2.3 | grep Digest

Mixing Pre-built and Custom Images

Combine pre-built images with custom builds:

services:
# Custom application (built from source)
app:
build: .
image: myapp:latest
x-ports:
- app.example.com:8000/https
depends_on:
- db
- redis

# Pre-built database
db:
image: postgres:16-alpine
volumes:
- db-data:/var/lib/postgresql/data

# Pre-built cache
redis:
image: redis:7-alpine

volumes:
db-data:

Update Pre-built Services

Update to New Version

Change the image tag in compose.yaml:

services:
app:
image: myapp:1.2.4 # Updated from 1.2.3

Deploy the update:

uc deploy

Uncloud will:

  1. Pull the new image to cluster machines
  2. Create new containers with zero downtime
  3. Remove old containers

Pull Latest Version

If using :latest tag, force pull new image:

uc deploy --pull

This ensures the newest version is pulled even if :latest already exists on cluster machines.

Common Patterns

Development vs Production Images

Use environment-specific images:

services:
app:
image: myapp:${ENV_TAG:-dev} # Defaults to 'dev'
x-ports:
- app.example.com:8000/https

Deploy to production:

ENV_TAG=v1.2.3 uc deploy

Multi-architecture Images

Use multi-arch images for clusters with mixed CPU architectures:

services:
app:
image: myapp:latest # Must be multi-arch image
platform: linux/amd64 # Optional: force specific platform

Build multi-arch images:

docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

Sidecar Patterns

Deploy application with sidecars:

services:
app:
image: myapp:latest
x-ports:
- app.example.com:8000/https

prometheus-exporter:
image: prom/node-exporter:latest
x-ports:
- metrics.example.com:9100/https

log-forwarder:
image: fluent/fluent-bit:latest
volumes:
- /var/log:/var/log:ro

Configuration Management

Environment Variables

Configure services with environment variables:

services:
app:
image: myapp:latest
environment:
DATABASE_URL: postgres://db:5432/myapp
REDIS_URL: redis://redis:6379
LOG_LEVEL: info

Config Files

Mount configuration files:

services:
nginx:
image: nginx:alpine
x-ports:
- www.example.com:80/https
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro

Secrets

Pass secrets via environment variables:

services:
app:
image: myapp:latest
environment:
API_KEY: ${API_KEY}
DB_PASSWORD: ${DB_PASSWORD}

Load from .env file:

# .env
API_KEY=secret123
DB_PASSWORD=pass456
uc deploy

Troubleshooting

Image Pull Failures

If image pull fails:

Error: failed to pull image: repository not found

Check:

  1. Image name and tag are correct
  2. Image exists in the registry
  3. You're authenticated (for private images)

Test locally:

docker pull myapp:latest

Authentication Issues

For private registries:

Error: pull access denied

Ensure Docker is authenticated:

docker login registry.example.com

Verify credentials are saved:

cat ~/.docker/config.json

Wrong Architecture

If you see:

Error: exec format error

The image architecture doesn't match your machine. Use multi-arch images or specify platform:

services:
app:
image: myapp:latest
platform: linux/amd64

Image Updates Not Applied

If deploying :latest but not seeing updates:

# Force pull new image
uc deploy --pull

Or use specific version tags instead of :latest.

Next Steps