Volumes

Not supported:

Image Volumes

A path an image declares as VOLUME gets a storage volume of its own, named after the service and mounted there:

services:
  store:
    image: ghcr.io/isso-comments/isso:latest

isso declares /config and /db, so store comes up with a volume at each. Without them Incus mounts a tmpfs over those paths, and isso's database is gone on the next restart.

This isn't limited to declared VOLUME paths: an application container's rootfs resets to the base image on every restart, so anything written directly into the filesystem outside a mount is gone the next time it restarts too. A bind mount target must already exist in the image, or live on storage that persists independently, since it cannot be created this way.

Declaring anything at the same target takes it over, which is how you choose the pool, the size, or that the path should not persist at all:

services:
  store:
    image: ghcr.io/isso-comments/isso:latest
    volumes:
      - db:/db # a volume of your own, with your own x-incus keys
      - type: tmpfs
        target: /config # deliberately empty on every start

One volume per service, shared by its replicas. Turn the whole thing off for a project with:

x-incus-compose:
  auto-volumes: false

The volume is named after the service and the path, vol-auto-store-db, so it cannot collide with a name you chose. An instance brings its volumes up and takes them down again, so down --volumes removes them - after a plain down there is no instance left to ask, and down --project is what clears them. The next up recreates the instance and adopts the same volumes.

Since: v1.3.0

Prefetching

A volume created empty starts from whatever the image holds at the path it is mounted over, as docker fills an empty volume from the image. This matters for a config directory the image ships:

services:
  web:
    image: docker.io/nginx:alpine
    volumes:
      - conf:/etc/nginx/conf.d

volumes:
  conf:

conf arrives holding the image's default.conf instead of being empty. Only volumes are filled, never bind mounts, and only on first creation - a volume that already exists is left alone, whatever the image says.

nocopy keeps it empty:

volumes:
  - type: volume
    source: conf
    target: /etc/nginx/conf.d
    volume:
      nocopy: true

Plain files and directories are copied, with their mode and owner. Symlinks, devices, sockets and fifos are skipped and named in a warning; docker copies them. A path the image does not have, or that holds nothing, leaves an empty volume and is not an error.

Since: v1.3.0