Open WebUI HQ
Flat isometric illustration of cyan and violet container cubes on purple plinths linked by dashed lines, with a pink badge and white arrow overhead
Getting Started

Install Open WebUI With Docker: Setup Guide

How to install Open WebUI with Docker: which image tag to run, the volume that holds everything, GPU flags, the first admin account, and safe updates.

By Open WebUI HQ Editorial · · 6 min read

Docker is the officially supported and recommended installation method for Open WebUI, and the whole application ships as one image. The project documents Python, Kubernetes, Podman and desktop paths as well, but the container route is the one where the fewest things can go wrong, provided you understand three decisions the install command quietly makes for you: which image tag you pulled, where your data lives, and which model backend the container can reach.

What you are actually installing

The official image is a single process that serves the web interface and the API together on container port 8080. That matters more than it sounds. When people report the “Open WebUI backend required” error, the usual cause is a port mapping that points at something other than 8080 inside the container, so the browser gets the interface shell but the interface’s own request to /api/config never reaches the backend.

The container does not include a language model. Unless you deliberately choose the bundled image, the model backend is a separate process that the container reaches over HTTP. If you want the background on that split before configuring anything, how Open WebUI and local models fit together covers which component owns which behaviour.

The command, flag by flag

The documented starting point pulls the image and runs it:

docker pull ghcr.io/open-webui/open-webui:main
docker run -d -p 3000:8080 -v open-webui:/app/backend/data \
  --name open-webui ghcr.io/open-webui/open-webui:main

-p 3000:8080 publishes the interface on port 3000 of the host and maps it to the container’s 8080. -v open-webui:/app/backend/data mounts a named Docker volume at the application’s data directory, which is the single thing standing between you and losing every account, conversation and indexed document the next time the container is recreated. The interface then answers at http://localhost:3000.

Images are published to two registries with identical content: ghcr.io/open-webui/open-webui and openwebui/open-webui on Docker Hub. Either works; substitute one for the other in any command.

One network requirement is easy to miss. WebSocket support is required from v0.5.0 onwards. A direct install on a local machine has this by default, but a proxy or corporate network that blocks upgrade requests produces a chat that hangs with no obvious error.

Choosing an image tag

The tag decides how the instance behaves over months, not just at install time.

TagWhat it gives youMoves over time
:main / :latestStandard image, newest build of the main branchYes, rolling
:main-slimSmaller image; downloads Whisper and embedding models on first useYes, rolling
:cudaNVIDIA GPU support, used with --gpus allYes, rolling
:ollamaOpen WebUI and Ollama bundled in one containerYes, rolling
:vX.Y.Z, :X.Y.Z, :X.YOne pinned stable releaseNo
:git-<sha>One exact commitNo
:devNewest build of the dev branchYes, rolling

Two points repay attention. First, :latest follows the main branch rather than the newest stable release, so it is not the conservative choice its name suggests; the documentation is explicit that production deployments should pin a version tag. Second, :dev builds can carry database migrations that are not backward compatible, so the project warns against ever sharing a data volume between a dev and a production instance. Give dev its own volume or do not run it at all.

GPU and bundled variants are just longer forms of the same command:

docker run -d -p 3000:8080 --gpus all -v open-webui:/app/backend/data \
  --name open-webui ghcr.io/open-webui/open-webui:cuda
docker run -d -p 3000:8080 --gpus=all -v ollama:/root/.ollama \
  -v open-webui:/app/backend/data --name open-webui --restart always \
  ghcr.io/open-webui/open-webui:ollama

The bundled :ollama image is the shortest path to a working stack on one machine, at the cost of coupling two upgrade cycles together. Note that it mounts a second volume for the models, because model weights are large and you do not want to re-download them on every container recreate.

The volume is the application

Everything stateful lives in /app/backend/data: the SQLite database with accounts, conversations, prompts and settings, plus uploaded files and the vector store. A named volume survives docker rm and image updates; a container started without -v keeps that data inside the writable container layer, where it is deleted the moment the container is removed. Docker’s own documentation treats named volumes as the preferred mechanism for exactly this reason.

Two habits follow. Back up the volume on a schedule rather than trusting the container. And before any major version upgrade, take a copy of it, because a failed migration is far easier to recover from a snapshot than from an interrupted upgrade.

First start, and the account decision

The first account registered becomes the administrator. Create it immediately after the first start rather than leaving a fresh instance reachable, particularly on any host that is not strictly local.

Authentication can be disabled entirely with WEBUI_AUTH=False for a genuinely single-user setup, and the documentation carries a warning worth repeating: you cannot switch between single-user mode and multi-account mode after making that change. Treat it as a one-way door and pick deliberately.

Pointing the container at a model backend

localhost inside a container means the container, not the host, which is the single most common cause of an install that starts cleanly and then shows an empty model list. Name an address the backend can actually reach instead. If Ollama runs on the same host as the container, that address is host.docker.internal:

docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway \
  -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
  -v open-webui:/app/backend/data --name open-webui --restart always \
  ghcr.io/open-webui/open-webui:main

If Ollama runs on a different machine, point the variable at that machine instead, which is the form the documentation gives for a remote backend:

docker run -d -p 3000:8080 -e OLLAMA_BASE_URL=https://example.com \
  -v open-webui:/app/backend/data --name open-webui --restart always \
  ghcr.io/open-webui/open-webui:main

The documented alternative for a same-host setup is host networking, which also changes the port you connect to:

docker run -d --network=host -v open-webui:/app/backend/data \
  -e OLLAMA_BASE_URL=http://127.0.0.1:11434 --name open-webui \
  --restart always ghcr.io/open-webui/open-webui:main

With --network=host there is no port mapping, so the interface answers on 8080 rather than 3000. If the model list still comes back empty after this, work through the Ollama connection fixes, which covers interface binding, saved configuration that overrides environment variables, and the timeout that makes an unreachable endpoint look like a slow one.

Size the machine before you pull models

The container itself is small. The memory question is entirely about the backend: model weights at your chosen quantization, the KV cache for the context length you configure, and an embedding model if you plan to use document retrieval, all resident at once. The Open WebUI VRAM and RAG sizer gives a starting estimate for a parameter count, quantization and context window before you commit to hardware or to a model that will spill into system RAM and crawl.

Behind a reverse proxy

A local-only instance needs none of this. The moment it sits behind TLS and a proxy, the documentation lists a specific set of settings, and skipping them produces symptoms that look like application bugs:

  • WEBUI_URL set to the real external URL, ideally before first startup. It is a persistent config value, so changing it later means the admin panel or a temporary ENABLE_PERSISTENT_CONFIG=false.
  • CORS_ALLOW_ORIGIN listing every origin users actually reach the instance through, semicolon separated. WebSocket connections respect CORS, so an incomplete list breaks chat rather than just logging a warning.
  • WEBUI_SESSION_COOKIE_SECURE and WEBUI_AUTH_COOKIE_SECURE enabled for HTTPS.
  • Upgrade and Connection headers forwarded, with proxy_http_version 1.1 on nginx.
  • proxy_buffering off and proxy_cache off on nginx. With buffering on, the proxy re-chunks the streamed response and splits markdown tokens across chunk boundaries, which is why replies arrive with visible ** and broken formatting that disappears when streaming is turned off.

Updating without losing anything

Updating a container means replacing it, not patching it. The documented manual sequence is to pull the new image, remove the old container, and run the same command again; the named volume carries the state across. Watchtower automates the same replacement if you prefer.

Neither approach protects you from a bad release. Pinning a version tag and updating deliberately does, and it turns “the interface changed overnight” into a decision you made.

A short pre-flight checklist

  • Named volume mounted at /app/backend/data, and a backup routine for it.
  • Host port mapped to container port 8080, unless you chose host networking.
  • Image tag chosen on purpose: pinned for anything that matters, rolling only for a scratch instance.
  • Admin account created at first start.
  • Model backend reachable from inside the container, not just from your browser.
  • Reverse proxy settings applied before exposing it beyond the local network.

If you are still deciding whether Open WebUI is the right front end at all, Open WebUI compared with LibreChat sets the two stacks side by side on architecture, configuration model and licensing.

Sources

  1. Open WebUI documentation: Quick Start
  2. Open WebUI documentation: Updating Open WebUI
  3. Open WebUI documentation: Connection Errors
  4. Docker documentation: Volumes

Related