Run your own Docker Compose
The "Custom Docker Composition" app runs any docker-compose.yml on your device, under a web address like every other app. You should know your way around Docker Compose. Everything else works like a normal install.
Install it
- Open Browse (or Template registry in advanced mode) and search for "Custom Docker Composition". It lives under "For tinkerers & developers".
- Click Install and pick a web address as for any app.
- In the settings, paste your compose file into the Docker Compose field.
- Set Primary service (the service that answers HTTP) and Primary port (the port inside that container). The web address is routed there.
- Confirm and unlock your device key when asked.
What the file may contain
The device checks the file before it runs anything. If something is not allowed, nothing starts and the install fails with the reason, for example services.web.ports forbidden.
A service may use these keys and no others: image, command, entrypoint, environment, volumes, depends_on, healthcheck, restart, labels, networks, tmpfs, read_only, user, working_dir, cap_drop, security_opt, stop_grace_period, stop_signal, sysctls, shm_size, mem_limit, cpus, init. Anything else is refused, including common ones like container_name, hostname, logging, ulimits and deploy. Delete those lines before you paste.
The refusals people run into most:
| Not allowed | Use instead |
|---|---|
build: | A prebuilt image from a registry (image:). |
privileged: true, cap_add, devices | Nothing. Containers run unprivileged. |
ports: and expose: | Primary service and Primary port. The web address reaches that port. Nothing opens on the device itself. |
Bind mounts of host paths (/home/pi/data:/data) | Named volumes. |
env_file, secrets, configs | environment: with ${VAR} values from the Environment field. |
network_mode, links, pid, ipc | Nothing. Services in the same file reach each other by service name. |
extends, profiles | One self-contained file. Every service in it runs. |
driver, driver_opts, external or name on a volume or network | Plain named volumes and networks. |
At the top level only services, volumes, networks, version and name are allowed.
services:
web:
image: ghcr.io/example/app:1.4.2
environment:
TZ: Europe/Berlin
APP_SECRET: ${APP_SECRET}
volumes:
- data:/var/lib/app
volumes:
data:
Values for ${VAR}
Below the compose field there is an Environment (.env) field. Put one KEY=value per line, for example APP_SECRET=something-long. The device saves it as the .env file next to your compose file, and Docker Compose fills every ${VAR} from it. That keeps secrets out of the compose text. Leave the field empty if you don't use variables.
Your data
Named volumes are stored on the device. They survive restarts and changes to the settings. When you remove the app, all of its volumes are deleted, and that can't be undone. Copy out what you want to keep first. Some templates mark volumes with x-obacht-data: true. The device accepts the marker, but it changes nothing today: those volumes are deleted like the rest. See Where your data lives.
Images must exist for your device's architecture: linux/arm64 on a Raspberry Pi and on a Mac, linux/amd64 on a Linux PC. An image that is only built for amd64 does not start on a Pi.
Change it later
Open the app page and Settings (in advanced mode the row action Configure), edit the fields, save. The device applies the new file: changed services are recreated, services you deleted from the file are removed. Named volumes stay. You can switch Primary service and Primary port the same way, the web address follows.
Logs shows one service at a time. With more than one service, pick the one you want at the top of the logs window.
Next: Run your own software.