Unregistry Architecture
Every Uncloud machine runs an embedded Unregistry server that:- Shares local images: Exposes images stored in the local Docker daemon
- Listens on port 5000: Uses the machine’s WireGuard mesh IP address
- Requires no configuration: Starts automatically with the Uncloud daemon
- Uses containerd backend: Only works when Docker uses containerd image store
Unregistry requires Docker with the containerd image store enabled. This is the default on modern Docker installations (20.10+). If you’re using the legacy image store, Uncloud will skip Unregistry setup but you can still use external registries.
How Unregistry Works
When you push an image to a machine usinguc build --push:
- Local build: Docker builds the image on your local machine
- Layer detection: Unregistry checks which image layers exist on the target machine
- Incremental transfer: Only missing layers are transferred over the network
- Direct import: Layers are imported directly into the remote Docker daemon
- Pushing to a registry
- Pulling from the registry
- Transferring all layers even if they already exist
Building Images with uc build
The uc build command builds images defined in your compose.yaml file using your local Docker daemon.
Basic Usage
compose.yaml
Build Arguments
Pass build-time variables to your Dockerfile:Building Dependencies
If your services reference other services in their build context:compose.yaml
Pushing Images to Cluster Machines
After building, you can push images to cluster machines in several ways:Push to All Machines
Push to Specific Machines
Push Using x-machines Extension
You can specify target machines in the compose file:compose.yaml
--push flag respects service-level x-machines unless you override with -m.
Manual Image Push
You can also push pre-built images without building:Image Distribution Across Machines
When you deploy a service, Uncloud needs the image on the target machine. Here’s how image distribution works:Pull Policies
Services can specify when to pull images:compose.yaml
always: Always pull from registry before starting containermissing(default): Pull only if image doesn’t exist locallynever: Never pull; fail if image missing
Image Pull Flow
- Check local availability: Machine checks if image exists in local Docker
- Try Unregistry peers: If missing, try pulling from other cluster machines
- Fall back to external registry: If not in cluster, pull from Docker Hub or configured registry
Authentication for External Registries
If pulling from private external registries:Layer Caching and Transfer
Unregistry’s biggest advantage is efficient layer transfer.How Layer Deduplication Works
Docker images are built from layers. When you push an image:- Layer enumeration: Unregistry lists all layers in the image
- Existence check: Queries target machine for which layers it already has
- Delta transfer: Only missing layers are transferred
- Reassembly: Target machine reassembles the image from existing + new layers
- Transfers all 205 MB
- Only transfers Layer 5 (5 MB)
- Layers 1-4 are already on the machine
Maximizing Layer Reuse
Optimize your Dockerfile for layer caching:Base Image Sharing
Base images (likenode:20-alpine, python:3.11) are typically large but rarely change. Once a base image exists on a machine, all services built from that base share those layers.
If you have 10 Node.js services on a machine:
- First service: Pulls full
node:20-alpine(50 MB) - Services 2-10: Reuse those layers (0 MB transfer)
Using External Registries
You can use external registries alongside Unregistry:Docker Hub
compose.yaml
Private Registries
compose.yaml
GitHub Container Registry
compose.yaml
Mixed Strategy
You can mix internal and external registries:compose.yaml
Image Management Commands
List Images on Machines
- Image repository and tag
- Image ID
- Size
- Which machines have the image
Check Image Availability
Before deploying, verify images exist:Remove Unused Images
Uncloud doesn’t automatically prune images. Clean up manually:Performance Considerations
Transfer Speed
Image transfer speed depends on:- Network bandwidth: Limited by machine-to-machine WireGuard throughput
- Layer size: Larger layers take longer to compress and transfer
- Compression: Unregistry compresses layers before transfer
- Local network: 50-100 MB/s
- Cross-region: 5-20 MB/s (limited by internet bandwidth)
Build Caching
Docker build cache is local to your machine. Builds always happen on your local Docker daemon, so:- Layer cache persists between builds
--no-cacheforces rebuilding all layers--pullensures base images are fresh
Storage Requirements
Each machine stores:- Images for services running on that machine
- Base images pulled for builds
- Dangling images from old deployments
Troubleshooting Image Issues
Image Not Found
If deployment fails with “image not found”:- Check image exists locally: Run
docker imageson your machine - Push to cluster: Run
uc image push <image-name> - Verify on target machine: SSH and run
docker images - Check pull policy: Ensure it’s not set to
never
Push Failures
Ifuc build --push fails:
- Check connectivity: Verify WireGuard mesh is working (
uc wg show) - Check Unregistry: Ensure port 5000 is accessible on target machines
- Verify containerd: Confirm Docker uses containerd image store
- Check logs: Review Uncloud daemon logs on target machine
Slow Transfers
If image transfers are slow:- Check network bandwidth: Test with
iperf3between machines - Optimize Dockerfile: Reduce layer sizes, merge RUN commands
- Use multi-stage builds: Keep final image small
- Pre-push base images: Push large base images once, reuse for all services
