Volumes provide persistent storage for containers. Uncloud supports named Docker volumes, bind mounts, and tmpfs mounts.
Volume types
Named volumes (volume)
Named volumes are managed by Docker and persist across container restarts:
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
References: pkg/api/volume.go:16-26
Bind mounts (bind)
Bind mounts map a host path to a container path:
services:
web:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- /var/log/nginx:/var/log/nginx
You can use long syntax for additional options:
services:
app:
image: myapp
volumes:
- type: bind
source: ./config
target: /etc/app
read_only: true
bind:
create_host_path: true
propagation: rprivate
Bind options:
create_host_path - Create host directory if it doesn’t exist
propagation - Mount propagation mode (rprivate, private, rshared, shared, rslave, slave)
References: pkg/api/volume.go:39-48, pkg/client/compose/service.go:295-312
Tmpfs mounts (tmpfs)
Tmpfs mounts are stored in memory and cleared when the container stops:
services:
app:
image: myapp
volumes:
- type: tmpfs
target: /tmp
tmpfs:
size: 10485760 # 10MB in bytes
mode: 1777 # Octal file permissions
References: pkg/api/volume.go:35, pkg/client/compose/service.go:355-368
Volume declaration
Declare volumes at the top level to use them in services:
services:
app:
image: myapp
volumes:
- app-data:/data
volumes:
app-data: # Simple declaration
app-cache: # Docker creates these with default settings
Volume options
Configure volume creation:
volumes:
app-data:
driver: local
driver_opts:
type: none
o: bind
device: /path/on/host
labels:
env: production
app: myapp
Volume options:
driver - Volume driver (default: local)
driver_opts - Driver-specific options
labels - Metadata labels
name - Override volume name
external - Use existing volume
References: pkg/api/volume.go:50-64, pkg/client/compose/service.go:314-343
External volumes
Reference volumes created outside Compose:
services:
app:
image: myapp
volumes:
- shared-data:/data
volumes:
shared-data:
external: true # Must already exist
External volumes must be created manually before deployment using uc volume create.
References: pkg/client/compose/deploy.go:168-192
Volume name aliasing
Use different names in compose.yaml vs Docker:
services:
app:
image: myapp
volumes:
- data-alias:/data
volumes:
data-alias:
name: production-data # Actual Docker volume name
Volume mounting
Short syntax
The short syntax is concise:
volumes:
- volume-name:/container/path
- /host/path:/container/path
- /host/path:/container/path:ro
- volume-name:/container/path:rw
Format: [source:]target[:mode]
source - Volume name or host path
target - Container path (must be absolute)
mode - ro (read-only) or rw (read-write, default)
Long syntax
The long syntax provides more control:
volumes:
- type: volume
source: app-data
target: /data
read_only: false
volume:
nocopy: true # Don't copy data from container to volume
subpath: app/logs # Mount subdirectory of volume
- type: bind
source: ./config
target: /etc/app
read_only: true
bind:
create_host_path: true
propagation: rprivate
References: pkg/api/volume.go:198-220
Cross-machine considerations
Volume placement
Named volumes are machine-local in Uncloud. When services use volumes, Uncloud ensures they run on the same machine as the volume.
services:
app:
image: myapp
volumes:
- app-data:/data
deploy:
replicas: 3 # All 3 replicas on same machine
volumes:
app-data:
All replicas of a service using the same named volume will be placed on the same machine to share the volume.
Multiple volumes
When multiple services use different volumes, Uncloud tries to optimize placement:
services:
app1:
image: app1
volumes:
- data1:/data
deploy:
replicas: 2
app2:
image: app2
volumes:
- data2:/data
deploy:
replicas: 2
volumes:
data1:
data2:
Uncloud can place data1 on one machine and data2 on another, distributing the services.
References: test/e2e/compose_deploy_test.go:206-388
Shared volumes
Multiple services can share the same volume, which constrains them to the same machine:
services:
writer:
image: writer
volumes:
- shared-data:/data
reader:
image: reader
volumes:
- shared-data:/data:ro # Read-only
volumes:
shared-data:
Both writer and reader will be placed on the same machine.
Global services with volumes
Global services (one container per machine) automatically create volumes on each machine:
services:
node-exporter:
image: prom/node-exporter
volumes:
- metrics:/metrics
deploy:
mode: global # One per machine
volumes:
metrics:
Uncloud creates a metrics volume on each machine for that machine’s container.
References: test/e2e/compose_deploy_test.go:562-601
Bind mount patterns
Configuration files
Mount individual config files:
services:
nginx:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl/cert.pem:/etc/nginx/ssl/cert.pem:ro
- ./ssl/key.pem:/etc/nginx/ssl/key.pem:ro
Application code
Mount application code for development:
services:
app:
image: node:20
command: npm run dev
volumes:
- ./src:/app/src:ro
- ./package.json:/app/package.json:ro
Shared host paths
Share host directories across services:
services:
processor:
image: processor
volumes:
- /data/input:/input:ro
- /data/output:/output
uploader:
image: uploader
volumes:
- /data/output:/data:ro
Volume drivers
Uncloud supports the local volume driver:
volumes:
data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/data
Only the local driver is currently supported. Network storage drivers (NFS, etc.) are not yet supported.
References: pkg/api/volume.go:24-26
Complete example
services:
web:
image: nginx:alpine
volumes:
# Named volume for content
- web-content:/usr/share/nginx/html:ro
# Bind mount for configuration
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# Tmpfs for temporary files
- type: tmpfs
target: /tmp
tmpfs:
size: 10485760
deploy:
replicas: 2
app:
image: myapp
volumes:
# Long syntax with options
- type: volume
source: app-data
target: /data
volume:
nocopy: true
# Logs volume shared with processor
- logs:/var/log/app
deploy:
replicas: 3
log-processor:
image: log-processor
volumes:
# Read-only access to logs
- logs:/logs:ro
deploy:
replicas: 1
metrics:
image: prom/node-exporter
volumes:
# Bind mount host metrics
- /proc:/host/proc:ro
- /sys:/host/sys:ro
deploy:
mode: global # One per machine
volumes:
web-content:
labels:
app: web
app-data:
driver: local
logs:
name: application-logs