Unraid Docker Compose is a plugin-based way to define, deploy, and manage multi-container stacks on your Unraid server using a single YAML file instead of clicking through individual Docker templates.
If you have been running containers through the Apps tab for a while, the jump to Unraid Docker Compose feels like moving from sticky notes to a written plan. Instead of ten separate template pages, you get one file that documents every image, volume, port, and environment variable in your stack.
That matters most when a single application needs several containers to work together. A media indexer with its own database, a search backend, and a cache layer is painful to wire up by hand, and almost impossible to rebuild from memory after a drive swap.
The plugin approach also keeps you inside Unraid. Stacks appear on the Docker tab, they survive reboots, and the same docker compose commands you would use on any Linux box work from the terminal.
In the walkthrough below, we cover installing the plugin, laying out appdata paths for archival data, converting existing templates into a compose file, and keeping the whole thing patched and recoverable.
Installing the Unraid Docker Compose Plugin
Installation takes about five minutes: confirm your Unraid version and array state, install Community Applications if it is missing, add the Docker Compose Manager plugin, then verify the binary from the terminal with docker compose version.
Prerequisites and Array Considerations
You need Unraid 6.10.0 or newer, administrative access to the web UI, and the Docker service enabled under Settings.
The array must be started before Docker or any compose stack will run. Anything living on /mnt/user is unavailable while the array is stopped, which is exactly why appdata paths matter later.
A cache pool (SSD or NVMe) is strongly recommended for appdata. Databases inside compose stacks write constantly, and spinning parity disks make that painful.
Installing the Community Applications Plugin
Open the Apps tab in the web UI. If Community Applications is not installed yet, Unraid presents an Install button on that page, so there is no need to hunt down a plugin URL.
Once Apps is available, search for Docker Compose Manager and click Install. The plugin deploys both the Compose plugin and the compose switch, so docker compose and the older docker-compose syntax both work.
Give the install a moment to finish, then reload the browser tab so the new UI elements appear.
Creating and Verifying the First Compose Project
Head to the Docker tab and scroll to the bottom. A new Compose section appears with an Add New Stack button.
Name the stack something descriptive, click the gear icon, choose Edit Stack, then Compose File, and paste your YAML. Save, then hit Compose Up.
To confirm the binary itself, open a terminal and run:
docker compose version
A version string means the plugin is healthy. Anything else usually points to an interrupted install.
How Compose Projects Work on Unraid
A compose project is one YAML file describing services, the images they run, the host paths they mount, and the network they share. Unraid stores each project in its own directory and treats it as a unit you bring up or tear down together.
Compose Files, Services, and Persistent Volumes
Each top-level entry under services: becomes one container. Volumes map a host path into the container so configuration and data survive image updates.
services:
archive-app:
image: example/archive-app:latest
container_name: archive-app
volumes:
- /mnt/user/appdata/archive-app:/config
- /mnt/user/archives:/data
ports:
- "8080:8080"
restart: unless-stopped
The rule we follow: configuration goes in appdata, bulk data goes on the array, and nothing important lives inside the container filesystem.
Choosing an Appdata and Project Directory
The plugin keeps stack definitions under /boot/config/plugins/compose.manager/projects/, which means they are backed up automatically whenever you back up the USB flash drive.
Appdata should point at /mnt/user/appdata/<service> so the cache pool absorbs the write load. For very database-heavy services, some of us use /mnt/cache/appdata/... directly to keep the mover from touching live files.
How Networks, Ports, and Environment Variables Work
Compose creates a private bridge network per project, so services reach each other by service name. A container connecting to postgres:5432 needs no published port at all.
Only publish ports you actually browse to. Environment variables handle PUID, PGID, TZ, and application settings, and Unraid’s usual values are PUID=99 and PGID=100.
Add labels with net.unraid.docker.icon and net.unraid.docker.webui and your compose containers get icons and WebUI links just like template-based ones.
Planning a Reliable Archival Data Stack
Good archival stacks start with a path convention, keep credentials out of the YAML, and only include containers that earn their keep. Decide those three things before you write a line of compose.
Mapping Storage Paths for Archives and Working Data
Separate the fast scratch area from the long-term archive. Downloads and unpacking belong on the cache pool; finished datasets belong on protected array shares.
| Purpose | Host Path | Notes |
|---|---|---|
| Service config | /mnt/user/appdata/<service> | Cache-backed, small, backed up nightly |
| Working/incomplete data | /mnt/user/downloads/incomplete | Cache only, high churn |
| Completed archives | /mnt/user/archives | Array shares with parity protection |
| Shared media library | /mnt/user/library | Read-mostly, mounted into several services |
Mount the same parent path into every container that needs it, for example /data, so hardlinks and instant moves work instead of slow copies.
Using Secrets and Configuration Files Safely
Keep API keys and database passwords in a .env file beside the compose file, then reference them as ${DB_PASSWORD}. The YAML stays shareable and the secrets stay local.
Set restrictive permissions on that file and never paste it into a forum post when asking for help. Redact keys the same way you would redact a password.
Selecting Containers for Home Lab Automation
Our baseline stack is intentionally small: an archival data organizer, an API synchronization hub for metadata, a download client, a reverse proxy, and a monitoring container.
For pulling Linux distributions, public domain archives, and other large datasets, a premium Usenet provider with long retention and SSL such as Newshosting or Easynews does the heavy lifting, and the container simply hands off NZB files. Guides on datahoarder.io cover provider retention and completion in more depth if you are still choosing one.
Migrating GUI-Managed Containers Safely
Migration is a documentation exercise more than a technical one. Record every setting, stop the old container without deleting appdata, rebuild it in YAML, and only remove the template once the new stack passes a real test.
Documenting Existing Container Settings
Open each container in the Docker tab, switch the view to Advanced, and copy the full Docker Run command that Unraid displays at the bottom of the edit page.
That single string contains every mapping you need: image tag, ports, volumes, environment variables, and extra parameters. Paste them all into a text file first.
Also note the container name, since some services store the hostname in their own configuration database.
Stopping Containers Without Losing Persistent Data
Stop the container, do not remove it yet. Stopping leaves appdata untouched, so a rollback is a single click away.
Take a copy of the appdata folder before you go further:
cp -a /mnt/user/appdata/myservice /mnt/user/backups/myservice-premigrate
That five-second habit has saved us more than once when a path typo pointed a fresh container at an empty config directory.
Converting Templates Into a Compose File
Translate the run command line by line. -p 8080:80 becomes a ports: entry, -v host:container becomes a volumes: entry, -e KEY=value becomes environment:.
Pin image tags rather than relying on latest for databases, and keep container names identical to the old ones so existing configs keep working. Group related services into one project so they share a network.
Testing the New Stack Before Removing Old Entries
Run docker compose up -d from the stack, then check the WebUI, log in, and confirm your library or archive index loaded rather than a first-run wizard.
Verify writes actually land in the right place by creating a test file through the app and locating it on the array. Once everything passes, delete the old template entry and its orphaned image.
Managing Updates, Logs, and Recovery
Day-to-day work comes down to four habits: controlled up and down cycles, reading logs when something refuses to start, pinning image versions so rollbacks are possible, and backing up both the YAML and the appdata behind it.
Starting, Stopping, and Rebuilding Services
From the Docker tab, each stack has Compose Up, Compose Down, and Update Stack buttons. From the terminal, the same operations look like this:
cd /boot/config/plugins/compose.manager/projects/mystack
docker compose up -d
docker compose down
docker compose up -d --force-recreate archive-app
Targeting one service by name is safer than recreating an entire stack when only one container misbehaves.
Reading Logs and Diagnosing Common Startup Failures
docker compose logs -f --tail=100 archive-app gets you straight to the useful part. Three failures account for most of what we see:
- Permission denied on a volume, fixed by correcting
PUID/PGIDor ownership on the host path - Port is already allocated, meaning another container or Unraid itself already claimed it
- Database connection refused, usually a service that started before its database was ready, solved with
depends_onplus a healthcheck
YAML indentation errors surface immediately as parse failures, so check spacing before blaming the image.
Updating Images With Controlled Rollbacks
Pull first, then recreate:
docker compose pull
docker compose up -d
Note the working tag in a comment inside your compose file before every update. Rolling back is then just editing the tag and running up -d again, which is far calmer than restoring a whole appdata folder at midnight.
Backing Up Compose Files and Appdata
Because projects live on the flash drive, a USB backup captures every stack definition. Appdata needs its own job, and the Appdata Backup plugin handles stopping containers, archiving, and restarting them on a schedule.
Keep one copy off the server. A backup that shares a chassis with the original is not a second copy.
Securing and Maintaining the Home Lab
Hardening a compose stack means publishing as few ports as possible, running containers as an unprivileged user, and watching capacity and parity health before they become emergencies.
Restricting Service Exposure and Administrative Access
Bind administrative interfaces to the LAN only. Prefixing a published port with an interface address, as in 127.0.0.1:8080:8080, keeps it off the wider network entirely.
Put a reverse proxy in front of anything that needs remote access, add authentication, and never forward a raw container port at the router. A WireGuard tunnel back into the home lab is simpler and safer than opening holes.
For traffic privacy on the download side, SSL from your provider plus a no-logs VPN covers the basics we write about regularly.
Applying Least-Privilege File Permissions
Run services with PUID=99 and PGID=100 rather than root, and add user: where the image supports it. Mount read-only wherever the container only needs to read:
volumes:
- /mnt/user/archives:/data:ro
Drop the Docker socket from anything that does not orchestrate containers. Mounting /var/run/docker.sock hands that container effective root on the host.
Monitoring Storage Capacity and Data Integrity
Set share-level minimum free space so a runaway download does not fill the cache pool and stall every database at once. Unraid notifications for disk utilization and SMART warnings should go to email or a push service, not just the dashboard.
Run monthly parity checks and quarterly checksum verification on archives using the File Integrity plugin or your own sha256sum manifests. Parity protects against drive failure; checksums catch silent corruption, and archival collections need both.
Frequently Asked Questions
How do I install and use Docker Compose on Unraid?
Where should Docker Compose files be stored on Unraid?
/boot/config/plugins/compose.manager/projects/<stack-name>/, which lives on the USB flash drive and is captured by flash backups. Appdata referenced by those files should sit under /mnt/user/appdata/ on your cache pool.Why does Unraid say that docker compose is not a docker command?
docker compose version in the terminal.What is the best Docker Compose Manager plugin for Unraid?
How do I convert an Unraid Docker template into a Compose file?
-p becomes ports, -v becomes volumes, -e becomes environment, and keep the same container name so existing appdata still matches.