Docker Compose for a Maintainable Open WebUI Setup
Move from one long docker run command to a single reviewable file - the bridge from a beginner setup to one you can actually maintain.
Why bother
The setup guide gets Open WebUI running with one long docker run command. That's the right call for a first setup - it's one thing to copy and paste. But it has a real cost once this becomes something you actually live with: every flag on that line is invisible the moment you close the terminal. Want to check what port it's mapped to, or whether the restart policy is actually set? You're re-reading the original guide, not looking at your own machine.
A compose file turns a command you ran once into a file you can actually look at.
Docker Compose doesn't change what Open WebUI does - it changes where its configuration lives. Instead of one command, you get one file: reviewable, editable, and the natural place to add anything else to this setup later.
The compose file
This file does exactly what the original docker run command does - same image, same port binding, same volume, same restart behavior. Nothing about Open WebUI's own behavior changes. Save it as docker-compose.yml in its own directory:
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: always
ports:
- "127.0.0.1:3000:8080"
volumes:
- open-webui:/app/backend/data
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
open-webui:
version: '3.8' line. Modern Docker Compose ignores it and prints a warning if it's there - current best practice is to just leave it out entirely, which is what this file does.
The extra_hosts block is doing the same job the original command's --add-host=host.docker.internal:host-gateway flag did - letting the container reach Ollama running on the host machine. If you skip it, you'll land back on Ollama Is Running, But Open WebUI Can't Connect.
Local, LAN, or remote?
That 127.0.0.1: prefix on the port line is what keeps this local-only by default - the same behavior as the setup guide's docker run command. This one file cleanly covers all three access levels this site teaches, just by changing that one line:
- Local only (the default above):
"127.0.0.1:3000:8080"- only this machine can reach it - LAN access:
"3000:8080"- reachable by other devices on your home network, same as Accessing Your Setup From Other Devices covers - Remote access: keep the local-only binding above, and use Tailscale to reach it from outside your network instead of widening the port binding at all
Change the line, then docker compose up -d again to apply it - no need to remove and recreate anything by hand.
Migrating your existing setup
Your chat history and settings live in the open-webui named volume, not inside the container itself - so as long as the compose file uses that exact same volume name, switching to Compose doesn't lose anything. Stop and remove the old container first:
docker rm -f open-webui
docker rm only removes the container - the named volume holding your actual data is untouched. Never run docker volume rm open-webui as part of this; that's the one command that actually deletes your chat history.
Then, from the same directory as your new docker-compose.yml:
docker compose up -d
Compose creates a new container, finds the existing open-webui volume already on disk, and connects to it - your chat history and settings are right where you left them.
Day-to-day commands
Once you're on Compose, a handful of commands replace everything you used to run manually - all from the same directory as the file:
- Start it:
docker compose up -d - Stop it (keeps your data):
docker compose down - Check the logs:
docker compose logs -f - Update to the latest image:
docker compose pull && docker compose up -d- see Keeping Everything Updated for the fuller update picture, including Ollama and your models
docker compose down -v casually. That extra -v flag deletes the named volumes along with the containers - it's the compose equivalent of the volume-removal warning above, just one flag away from a command you'll actually type often.
What actually goes wrong
"no configuration file provided" error
docker compose commands only work from the same directory as docker-compose.yml - or with an explicit -f /path/to/docker-compose.yml flag from anywhere else. This is the most common first mistake, not a real configuration problem.
Compose created a new, empty setup instead of finding your data
The volume name in the file has to match your existing volume exactly. Check what actually exists first:
docker volume ls
If the name in your compose file doesn't match what's listed there, Compose creates a fresh, empty volume with the new name instead of reusing the old one - your original data is still safe on disk, just not connected to the new container.
Container keeps restarting after switching to Compose
Same diagnosis as before Compose was involved - see Docker Container Keeps Restarting. docker compose logs -f is the compose equivalent of docker logs for finding the actual error.
Common questions
Do I need to remove my existing container first?
Does this replace the original docker run command forever?
Can I add more services to this file later?
Go deeper
This guide covers the exact setup this site already teaches. For everything else Compose can do:
Changelog
- 2026-08-31: Changed the default compose file to bind Open WebUI to 127.0.0.1 (local-only), matching the setup guide, and added a Local/LAN/Remote section.
Written from hands-on security operations experience. More about this site →