# Compose support

Generated from the code · as of CLI 0.6.0

Your `docker-compose.yml` runs on OmniArc as you wrote it. A few things compose can express have no meaning inside an arc, and `omniarc check` and `omniarc deploy` stop on those before anything is uploaded, with the error [`unsupported`](https://docs.omniarc.eu/errors/unsupported.md). A few more run, but not quite the way compose runs them on your laptop, and `omniarc check` prints a note.

The Field column is spelled the way `omniarc check` prints it. Where it holds a path, as in `volumes[./src]`, read it as the source of one of your own volumes.

## Refused

`omniarc check` stops on each of these, and so does the deploy. Change your compose file as the second column says.

| Field | What to know, and what to do instead |
| --- | --- |
| `build.context` | A URL as the build context: a Git repository, for example, is fetched when the image is built, and builds on a node do not fetch it. Put the source in your project and point `context` at that directory. |
| `build.context` | A build context outside the project: it is not in what you deploy. Move it inside the project. |
| `build.context` | A build context that is not a directory in what you deploy: a Git submodule, a nested repository or ignored files do not make it into the upload, and the build would fail on the node after the upload. Put the files in your project as ordinary files. |
| `build.dockerfile` | The Dockerfile is outside the build context. Move it inside the project. |
| `build.additional_contexts` | Needs BuildKit, and nodes build with Buildah. Copy what the build needs into the main build context. |
| `build.secrets` | Needs BuildKit, and nodes build with Buildah. Keep the secret out of the image: set it as a variable with `omniarc env set` and read it when the container starts. |
| `build.ssh` | Needs BuildKit, and nodes build with Buildah. Put private dependencies in your project before you deploy. |
| `build.cache_to` | Needs BuildKit, and nodes build with Buildah. Remove it. |
| `build.platforms` | Building for several platforms at once needs BuildKit. Nodes build for linux/amd64: list `linux/amd64`, or remove the key. |
| `build.privileged` | A privileged build cannot run on a node. Remove `privileged: true` from the `build` section. |
| `privileged` | A privileged container cannot start in an arc. Remove `privileged: true`; if the service needs a specific capability, add it with `cap_add`. |
| `devices` | Host devices are not available to an arc's services. Remove the entry. |
| `device_cgroup_rules` | Host devices are not available to an arc's services. Remove the rule. |
| `gpus` | No GPUs reach an arc. Remove the entry. |
| `runtime` | Other container runtimes, such as `nvidia`, are not available. Remove the entry. |
| `cgroup_parent` | Placing a container in a cgroup of the host is not available. Remove the entry. |
| `userns_mode` | The host's user namespace is not available to an arc. Remove the entry. |
| `platform` | Services run as linux/amd64, and nodes do not emulate other platforms. Set `platform: linux/amd64`, or remove the key. |
| `env_file` | An `env_file` whose name is not in the `.env` family (`vars.txt`), or one outside the project, is not read on a node. Move its values into the arc's `.env` with `omniarc env push`, then use `${VAR}` in compose or `env_file: .env`. |
| `label_file` | A `label_file` inside a writable bind mount of the project is read at every deploy, and a service could rewrite it. Keep the file outside every writable bind. |
| `networks.ext` | An external network is one OmniArc did not create, and an arc owns its networks. Remove `external: true` and let compose create the network. |
| `networks.mv` | `macvlan` and `ipvlan` attach to a network interface of the host, which an arc does not have. Use the default bridge network. |
| `volumes[/srv/abs]` | A bind mount from an absolute path, a path that leaves the project (`../data`) or your home directory (`~/data`) does not exist on a node. Use a named volume, or a path inside your project. A read-only mount of `/etc/localtime` or `/etc/timezone` is allowed. |
| `volumes[.]` | A writable bind mount of the whole project directory, of a `.env` file or of `arc.yaml` cannot be kept across deploys. Nor can any mount inside a writable bind of the project, read-only too, or a writable bind that holds a compose file: a service could rewrite what is there or replace it with a link. Bind only the directory the service writes to, keep what compose reads outside it, or add `:ro` to mount it read-only. |
| `volumes[/run/podman/podman.sock]` | Podman's own API socket is not available to services, so a service cannot start or change containers. To read the arc's containers, as Traefik's docker provider does, bind `/var/run/docker.sock` instead. |
| `volumes.nfsvol` | A volume whose `driver_opts` bind a path or mount a network share is not permitted. Use a plain named volume. |
| `volumes.ext` | An external volume is one OmniArc did not create, so it cannot be branched. Remove `external: true` and let compose create the volume. |
| `volumes.plug` | Only the `local` volume driver exists in an arc. Remove `driver`. |
| `configs.esc` | A config file outside the project directory is not in what you deploy. Move the file inside the project. |
| `secrets.fs` | A secret read from a file in your project would be kept on the arc's disk. Take it from the arc's `.env` with an `environment:` source instead, and set the value with `omniarc env set`. |
| `healthcheck.interval` | Each health check costs CPU, so `interval` must be 5s or more. Raise it. |
| `healthcheck.start_interval` | The container engine rejects `start_interval`, and the arc starts health checks every 500 ms itself. Remove it. |
| `logging.driver` | Only the `json-file`, `local` and `none` log drivers exist. Use one of them, or remove `logging`. |
| `external_links` | Nothing outside the project can be reached by name. Remove it, and put what the service talks to in the same compose file. |
| `compose` | Each file in the `compose:` list of `arc.yaml` must be a plain file inside the project directory, written out literally: not a URL, an absolute path, a `~` path, a path that leaves the project, or one with a `${VAR}` in it. Fix the path, or move the file inside the project. |
| `include` | A remote `include:`, a URL or a Git repository, is fetched over the network and is not part of what you deploy. Copy the file into your project and include it by its path. |
| `include` | An `include:` path that leaves the project directory is not in what you deploy. Move the file inside the project. |
| `include` | An `include:` path with a `${VAR}` in it is refused: write the path out literally, so that what you deploy is exactly what compose reads. |
| `include` | An `env_file` on an `include:` would carry values onto the arc's disk by a second route. Put the values in the arc's `.env` with `omniarc env push`. |
| `include` | An `include:` whose `project_directory` is outside the project, or has a `${VAR}` in it, is refused. Keep it inside the project and write it literally. |
| `extends` | A remote `extends: {file: ...}`, a URL or a Git repository, is fetched over the network and is not part of what you deploy. Copy the file into your project and extend it by its path. |
| `extends` | An `extends: {file: ...}` path that leaves the project directory is not in what you deploy. Move the file inside the project. |
| `extends` | An `extends: {file: ...}` path with a `${VAR}` in it is refused: write the path out literally, so that what you deploy is exactly what compose reads. |

## Runs with a caveat

These run. `omniarc check` prints the note so it does not surprise you later.

| Field | What to know, and what to do instead |
| --- | --- |
| `env_file` | An `env_file` named like a `.env` file (`./apps/api/.env`, `config/app.env`) reads the arc's one `.env`, as `env_file: .env` does. Send its values with `omniarc env push`; `--file` repeated merges several files into it. |
| `volumes[./data]` | A writable bind mount of a path inside the project is project state: what the service writes there is kept across deploys, outside what you deploy, and branches with the arc like a named volume (a `branch: false` service's starts empty). The first deploy fills it from that path in your project, if it has one; later deploys keep what the service wrote and ignore the project's copy, and a branch where the service starts empty does not get it back. |
| `build` | Images are built with Buildah, not BuildKit. Most Dockerfiles build the same; the BuildKit-only options are listed above as refused. |
| `build.platforms` | A single platform other than linux/amd64 is built as linux/amd64, so the image is amd64. Set it to `linux/amd64`, or remove the key. |
| `network_mode` | `host` is the arc's own network, shared with its other services. It is never the network of the machine the arc runs on. |
| `pid` | `host` means the arc, not the machine it runs on. |
| `ipc` | `host` means the arc, not the machine it runs on. |
| `uts` | `host` means the arc, not the machine it runs on. |
| `cgroup` | `host` means the arc, not the machine it runs on. |
| `cap_add` | Capabilities are limited by the arc's isolation (its user namespace, AppArmor and seccomp). Some, such as `SYS_MODULE`, do nothing; `omniarc check` names the ones in your file that do. |
| `security_opt` | Applies only within the arc's isolation: its user namespace, AppArmor and seccomp. |
| `sysctls` | `net.*` settings are per arc and work. A setting of the whole kernel, such as `kernel.shmmax`, fails when the service starts, with the kernel's error. |
| `secrets.es` | A secret from an `environment:` source is written to the container's writable layer on the arc's disk, so a branch made from the arc starts with it. |
| `restart` | Honoured while the arc runs. After a sleep and wake, the containers that were running are started again, and one-shot containers that had exited stay exited. |
| `deploy` | `placement`, `update_config`, `rollback_config` and `mode: global` are settings for Swarm, which compose ignores, and so does the arc. |
| `develop` | `watch` is a feature for your laptop and is ignored. |
| `volumes[/var/run/docker.sock]` | A read-only view of the arc's own containers, enough for Traefik's docker provider and other tools that list containers and follow events. It answers GET and HEAD only, and refuses exec, attach, file copies (archive), export and image save, so a service can look but not start, stop or enter a container. Looking includes what `docker inspect` and `docker logs` show for every service of the arc, environment values among them. `/run/docker.sock` is the same socket. It costs the arc memory: the socket's own server runs in every arc (about 0.5 MB), and the container API behind it starts when asked and stops after 5 s idle, but a client that follows events, as Traefik does, keeps it running (about 54 MB, measured 20 Oct 2026). |

## Everything else

Everything else runs as compose runs it.
