incus-compose

A drop-in replacement for docker compose that runs your compose.yaml on Incus - with the full Incus API available as an escape hatch when you need more than the Compose spec covers.

services:
  db:
    image: docker.io/postgres:18-alpine
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 2G

  web:
    image: docker.io/nginx:alpine
    depends_on:
      db: { condition: service_healthy }
    ports:
      - "8080:80"
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 512M
incus-compose up

A plain compose file, running unchanged.

flowchart LR
    subgraph F["your files"]
        direction TB
        CY[compose.yaml]
        CI["compose.incus.yaml<br/>optional Incus overrides"]
        DE[.env]
    end

    F --> IC[incus-compose]
    IC --> P

    subgraph P["one Incus project per compose project"]
        direction TB
        IMG["images<br/>copied from the shared cache"]
        NET["bridge networks<br/>real IPs and DNS"]
        VOL["storage volumes<br/>UID/GID shifted"]
        INST["instances<br/>web-1, db-1, ..."]
        HD["ic-healthd<br/>healthchecks and restarts"]
    end

New to Incus? See Why Incus? for what the platform brings over a classic OCI engine setup.

Demos

Features

Drop-in. All the commands you know - up, down, start, stop, restart, pause, logs, exec, cp, top, ps, config, build - parsing via compose-go with .env interpolation, profiles, depends_on, secrets, and configs. See the CLI reference and the compatibility matrix.

Operable. Health checks, restart policies, and depends_on: service_healthy ordering via the ic-healthd sidecar; scaling with up --scale; project isolation; live progress for pulls and lifecycle. See Health Checking.

Fast images. OCI pulls from any registry, a two-stage cache that survives down/up and dodges rate limits, and local builds via Podman/Docker. See Builds.

Real networking and storage. Bridge networks with static IPs, port publishing via proxy devices or kernel NAT, volumes with UID/GID shifting, seeded bind mounts, and per-volume pool placement.

Incus-native when you want it. Every instance, network, and volume option passes straight through via x-incus; x-incus-compose adds devices (GPU, USB, raw disk), project-wide resource limits, and healthd tuning. See Compose Compatibility.

Extensions. incus-compose backup snapshots a project's data volumes into a backup project - create, list, verify, restore, and prune - so a stack's state survives the project itself, and incus-compose port-forward forwards a local TCP port into an instance, published or not. See backup and port-forward.

Quick Start

Requires Incus 7.0.1 (LTS) or 7.2+, podman or docker for image building and an Incus https remote (needed for healthchecking) with OCI registries added. See Getting Started for the full setup walkthrough.

Install the latest release:

curl -sSfL https://raw.githubusercontent.com/lxc/incus-compose/main/install.sh | sh -s -- -b ~/.local/bin

Or grab a prebuilt archive from the Releases Page. On Arch Linux, install incus-compose-bin (or incus-compose-git for builds from main) from the AUR.

Then point it at your existing compose.yaml:

# Start services
incus-compose up -d

# View logs
incus-compose logs -f

# List running services
incus-compose list

# Stop and remove
incus-compose down

Quick Links

Support and community

The following channels are available for questions and discussion around incus-compose.

Bug reports

You can file bug reports and feature requests at: https://github.com/lxc/incus-compose/issues/new

Community support

Community support is handled at: https://discuss.linuxcontainers.org

Contributing

Fixes and new features are greatly appreciated. Make sure to read our contributing guidelines first!