On OpenMediaVault 8, Docker and Docker Compose run through the openmediavault-compose plugin from omv-extras. Enable the Docker repo under System > omv-extras, install openmediavault-compose 8.x from System > Plugins, then point its Settings tab at shared folders for compose files, data, backups and Docker storage. Every stack is then managed from the web interface.
Older guides tell you to click the Portainer button in omv-extras. That button went away in May 2023, when omv-extras 6.3 handed Docker installation to the compose plugin, according to the omv-extras changelog. A current install means OpenMediaVault 8 “Synchrony” on Debian 13, since OMV 7 hit end of life in June 2026 per the release table. There the compose plugin is the supported route, with compose files in ordinary shared folders you can back up like anything else. What follows is that setup, in the order that avoids redoing it at month nine.
Who this is for, and who should skip it
You want a handful of containers on the box that already serves your SMB shares: a media server, a photo backup target, maybe a download client. OMV 8 supports AMD64 and ARM64 only, so 32-bit boards are out.
For an ARM64 board, complete the OpenMediaVault on a Raspberry Pi installation before adding Compose. It covers the base OS, wired networking and data disk that this container guide assumes are already working.
Skip it if you want a marketplace with app icons. OMV treats Docker as an add-on to a general-purpose Debian system, the appeal for anyone who knows docker compose and the frustration for anyone who does not. Two services on an N100 do not need Kubernetes.
What does the OMV compose plugin install?
The openmediavault-compose plugin installs Docker Engine (docker-ce, docker-ce-cli, containerd.io), the docker-compose-plugin package that provides docker compose, and docker-buildx-plugin, all from Docker’s own apt repository rather than Debian’s. When you set a Docker storage path it also writes /etc/docker/daemon.json. The plugin itself is the web interface over those tools.
The list comes from the plugin’s Salt deploy state:
| Component | Package or file | Role on the NAS |
|---|---|---|
| Docker Engine | docker-ce, docker-ce-cli, containerd.io | Runs the containers |
| Compose v2 | docker-compose-plugin | The docker compose command behind Up, Pull and Down |
| Image builds | docker-buildx-plugin | Builds images from the Dockerfiles tab |
| Daemon config | /etc/docker/daemon.json | Sets data-root to your storage path, json-file logs capped at Log File Max Size (50 MB default) with 3 files kept, live-restore if enabled |
| Web terminal | openmediavault-cterm | Installed alongside unless OMV_NO_CTERM_DEPENDENCY=yes |
No Docker version is pinned, so you get whatever Docker’s repository currently ships. Docker’s Debian install page lists Debian 13 Trixie among its supported releases and both amd64 and arm64 among its architectures, which covers everything OMV 8 runs on. The plugin moves faster than OMV itself: its changelog starts the 8.x line on 28 September 2025, three months before OMV 8.0.1 was announced on 24 December 2025, and shows eight releases between 2 September and 7 October 2026, the last being 8.2.2. Expect a higher number by the time you install.
Two cautions follow. Debian’s own docker.io package is on Docker’s list of unofficial packages that conflict with the official ones and must be removed first, so do not apt install it next to the plugin. And the plugin fully manages only containers it created, per the plugin wiki; ones started with a bare docker run stay partly invisible in its tabs until Autocompose turns them into files.
Step 1: omv-extras, the Docker repo, the plugin
omv-extras is the third-party plugin repository that carries the compose plugin. Install it as root with the one-liner from the maintainers’ README:
wget -O - https://github.com/OpenMediaVault-Plugin-Developers/packages/raw/master/install | bash
Before piping anything into bash as root, read what omv-extras changes on an OMV 8 system. Then, in the web interface, following the wiki’s Docker in OMV 8 page:
- SYSTEM > OMV-EXTRAS, enable DOCKER REPO, SAVE. This adds Docker’s own apt repository, the source of the
docker-compose-pluginpackage that providesdocker compose. - SYSTEM > PLUGINS, select openmediavault-compose 8.x, INSTALL.
Since plugin 8.1 (December 2025) the install enables the Docker repo by itself, so the first step is now a check rather than a requirement. The install pulls in openmediavault-sharerootfs as a dependency. Leave it alone: uninstalling it removes the compose plugin with it.
Step 2: decide where everything lives before you start anything
This is the step people rush, and the one that hurts later. The plugin’s Settings tab (SERVICES > COMPOSE > SETTINGS) wants shared folders for four things. Keep the wiki’s names, since forum answers assume them:
- appdata: compose files, one subfolder per stack, plus each stack’s config directories. A relative path such as
./configlands here, next to the YAML. - data: bulk data like a media library. Any compose file can reference it through the special string
CHANGE_TO_COMPOSE_DATA_PATH, which the plugin swaps for the folder’s real path. - backup_compose: where the scheduled backup writes.
- docker: Docker’s own storage, which holds images, layers and named volumes. The default is
/var/lib/dockeron the OS disk. Change it, then click Reinstall Docker.
The wiki’s rules for that docker folder are specific: not on the OS drive or a USB stick, not on a mergerfs pool, not on NTFS, preferably ext4 on a separate drive, entered as a full absolute path with no symlinks. The mergerfs rule catches people, because a pool looks like a normal directory right up until Docker’s layer files are spread across disks. Carve out a plain ext4 filesystem for Docker instead, sized per the FAQ below; the OMV 8 hardware requirements cover the OS disk it should not share. The layering in OpenMediaVault NAS planning applies here too: filesystem first, shared folder second, service last.
For NVIDIA hardware transcoding, the wiki says to leave the storage path empty, since changing it can corrupt the NVIDIA configuration when OMV reconfigures.
The same field decides who owns daemon.json. With a path set, the plugin writes that file on every apply, so hand edits do not survive; for custom daemon settings the wiki says to leave the field empty and edit /etc/docker/daemon.json yourself. Live Restore, in the same section, keeps containers running while the Docker daemon restarts.
By default the plugin creates compose folders and files restricted to root. The wiki recommends a dedicated appuser created in the GUI with rights on the shared folders, and never running containers as admin (UID 998) or root (UID 0). Do not add appuser to the docker group either: the wiki notes that any member of that group can escalate to root. If shared folders are new to you, creating a shared folder in OpenMediaVault covers the privileges step.
After Reinstall Docker, confirm the result from the shell:
docker compose version
docker info | grep -E "Docker Root Dir|Logging Driver|Live Restore"
In the docker info output, Docker Root Dir should show your docker shared folder’s path rather than /var/lib/docker. If it still shows the default, the storage path did not apply.
Step 3: the first stack
OMV 8’s plugin looks up user, group, time zone and shared-folder values itself through ${{ }} placeholders, added in plugin 8.0.4 and 8.0.5 in December 2025. Files > Create, name it jellyfin, and paste this, adapted from the LinuxServer.io Jellyfin reference and the wiki’s own Jellyfin example:
services:
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=${{ uid:"appuser" }}
- PGID=${{ gid:"users" }}
- TZ=${{ tz }}
volumes:
- ./config:/config
- CHANGE_TO_COMPOSE_DATA_PATH/movies:/data/movies:ro
- CHANGE_TO_COMPOSE_DATA_PATH/tvshows:/data/tvshows:ro
ports:
- 8096:8096
restart: unless-stopped
Click Check to validate the file, then Up. The first Up downloads the image, and the Services tab shows the logs. Jellyfin answers on port 8096.
Before the container starts, the plugin swaps ${{ uid:"appuser" }} for appuser’s UID, ${{ gid:"users" }} for 100 (the group every GUI-created user lands in) and ${{ tz }} for the server’s time zone, so there is no id appuser output to copy by hand. For Intel Quick Sync transcoding, the wiki’s version adds /dev/dri:/dev/dri under devices: and puts appuser in the render and video groups.
Upgraded from OMV 7 with omv-release-upgrade, the tool the OMV 8 announcement names, and your files read PUID=${PUID} from a global environment file? Leave them. The wiki calls global variables optional on OMV 8, not removed, and since 8.0.6 the placeholders also expand inside that file. The plugin keeps it as global.env in the appdata root and overwrites the copy on disk, so edit it through the Files tab’s global environment editor, not over SMB.
Three deliberate choices in that file. PUID and PGID run the container’s process as your appuser, so the files it writes belong to someone you can log in as. LinuxServer’s docs put it plainly: root-owned files become inaccessible to you. The config directory is a bind mount into appdata rather than a named volume. Docker’s docs prefer volumes because Docker manages them, but that buries your config inside the docker storage folder, invisible to SMB and awkward to back up. On a NAS a bind mount you can see wins. The documented trade-off, that a bind mount ties the container to the host’s directory layout, is a feature here. And unless-stopped, one of the four documented restart policies, survives reboots without resurrecting containers you deliberately stopped.
Which containers earn a permanent place is a separate question, and SelfhostRealm’s compose stack framework answers it honestly.
What does CHANGE_TO_COMPOSE_DATA_PATH do?
CHANGE_TO_COMPOSE_DATA_PATH is a literal placeholder that the compose plugin replaces with the absolute path of the shared folder chosen as Data under Services > Compose > Settings. Since plugin 7.0.9 (March 2024), a compose file containing it fails with an error when no Data folder is set, so set Data before running any example.
It is the older of two placeholder systems, and the templates under Files > Add from example still rely on it. OMV 8 added a general form that names any shared folder, per the plugin changelog and the wiki:
| Placeholder | Becomes | Available since |
|---|---|---|
CHANGE_TO_COMPOSE_DATA_PATH | Path of the Data shared folder in Settings | 6.x plugin (by July 2023), still supported |
${{ sf:"media" }} | Absolute path of the shared folder named media | 8.0.4, December 2025 |
${{ uid:"appuser" }} | That user’s UID | 8.0.5, December 2025 |
${{ gid:"users" }} | That group’s GID (100 for users) | 8.0.5, December 2025 |
${{ tz }} | The server’s time zone, such as Europe/Madrid | 8.0.5, December 2025 |
The sf form resolves in compose, override, env and config files, and it removes the one-folder limit: a stack that reads movies from one shared folder and photos from another can name both. Use CHANGE_TO_COMPOSE_DATA_PATH when every stack reads from a single bulk folder and you want the examples to run unmodified. Use sf when data is split across shared folders, such as a mergerfs pool next to a plain disk. Since 8.1.25 (September 2026), changing a shared folder that a placeholder references marks the compose module dirty, so OMV asks you to apply the change.
If a container starts but sees an empty directory, look at the path after the placeholder for a typo, then at appuser’s privileges on that shared folder. Check validates syntax, not permissions.
Backups and the restore drill
The Schedule tab runs a backup job: it stops the containers, copies the compose folder and each stack’s data with rsync, then restarts them. Volumes are included only below the Max Size threshold, 1 GB by default (0 removes the limit), unless you append # BACKUP or # SKIP_BACKUP to the volume line. Read-only mounts are never copied, and global.env goes along.
That is a consistent snapshot, not versioned history, and it lands on the same NAS. Treat backup_compose as the first hop, then rsync it to something that is not this machine. The 3-2-1 approach for a self-hosted stack covers the off-site copy.
Run the restore drill once, before you need it: on a scratch install, point Settings at restored copies of the folders, Files > Import the stacks, then Up. More than twenty minutes means the layout is too clever.
Networking and updates
Bridge networking with published ports is right for nearly everything. The Networks tab exists for the exception: a container that needs its own LAN address, Pi-hole being the classic case, gets a macvlan network with your interface as parent, your subnet and gateway, and a small reserved IP range. Keep it all on the LAN or behind a VPN. Forwarding port 8096 on the router is how a Jellyfin login page ends up indexed by internet scanners. Docker’s Debian install page adds a second reason for care: ports Docker publishes bypass ufw and firewalld rules, so a host firewall will not hide them.
For updates, the Schedule tab’s update job pulls images and recreates containers. The Files tab has Pull, Up and Prune for doing it by hand. Autocompose writes a file from a container you started on the command line. Arriving from Portainer, use Import from Portainer on the Files tab, added in 8.1.13 (April 2026), which pulls stacks across with a Portainer API key or a username and password. The maintainers’ forum guide describes the manual route, which still works: copy each stack’s text out, delete it, recreate it here. Two containers, one evening, and a NAS that documents its own container layout in a folder you can read.
FAQ
does openmediavault 8 still support portainer?
Not as a built-in installer. omv-extras removed its Portainer button in version 6.3 (May 2023), and the OMV 8 compose plugin’s changelog mentions Portainer only as a migration source: since 8.1.13 (April 2026), the Files tab can import stacks from it using an API key or username and password. Portainer itself still runs as an ordinary container.
where does omv store docker images and volumes?
In the Docker storage path set under Services > Compose > Settings, which the plugin writes to /etc/docker/daemon.json as data-root. Left empty, it is /var/lib/docker on the OS disk. Compose files and bind-mounted config live separately in the appdata shared folder. Run docker info and read the Docker Root Dir line to confirm.
how much disk space does docker need on openmediavault?
The omv-extras wiki calls 60 to 100 GB a sensible minimum for the Docker drive and suggests 250 to 500 GB or more for large media libraries. Images, layers and named volumes all land there. Its reference layout gives Docker a dedicated NVMe drive, kept off the OS disk and out of any mergerfs pool.
how do i update docker containers in openmediavault?
Two ways. Add an update job in the Schedule tab, which pulls newer images for the compose files you select. Or update one container by hand: Services tab, select it, Pull; Files tab, select its file, Up; then Prune and Image to remove the old image. Pin a version tag for anything that must not change overnight.
can omv 8 use podman instead of docker?
Experimentally. openmediavault-compose 8.1, released in December 2025, added Podman support flagged as experimental. In that mode the plugin installs podman, podman-docker and aardvark-dns in place of docker-ce, with docker-compose-plugin still installed for both runtimes. Docker is the runtime the wiki’s walkthrough and this guide use.