Dockge
A fast, reactive, self-hosted Docker Compose stack manager.
The stack
Generated output
services:
dockge:
image: docker.io/louislam/dockge:1.5.0@sha256:335c6368b880ecc203236ed89e6e5232e0d6578e8ef5920e4a502390451502bf
restart: unless-stopped
environment:
DOCKGE_STACKS_DIR: ${STACKS_DIR}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockge-data:/app/data
- ${STACKS_DIR}:${STACKS_DIR}
volumes:
dockge-data: {}
# Caddyfile for Dockge
# Replace dockge.example.com with your real domain. Caddy issues TLS automatically.
dockge.example.com {
encode zstd gzip
reverse_proxy dockge:5001
}
# Traefik labels for Dockge
# Merge into the dockge service in docker-compose.yml.
# Assumes an external Traefik network named "proxy" and a
# certresolver named "letsencrypt". Replace dockge.example.com.
services:
dockge:
labels:
traefik.enable: "true"
traefik.http.routers.dockge.rule: Host(`dockge.example.com`)
traefik.http.routers.dockge.entrypoints: websecure
traefik.http.routers.dockge.tls: "true"
traefik.http.routers.dockge.tls.certresolver: letsencrypt
traefik.http.services.dockge.loadbalancer.server.port: "5001"
networks:
- proxy
- default
networks:
proxy:
external: true
Replace dockge.example.com with your domain. Generate secrets below.
Environment
.env with generated secrets
Secrets are generated in your browser via crypto.getRandomValues. Nothing is sent anywhere.
Server-rendered .env template
# Host directory where Dockge reads and writes your compose stacks. It must resolve to the same path inside and outside the container, because Dockge shells out to `docker compose` with host paths. Used for both the bind mount and DOCKGE_STACKS_DIR. STACKS_DIR=/opt/stacks
About
What is Dockge?
Dockge is a self-hosted manager for Docker Compose stacks, from the author of Uptime Kuma. It gives you a clean, reactive web UI for the work you would otherwise do over SSH: write a `compose.yaml`, bring the stack up, watch the logs stream, edit, redeploy. Unlike heavier panels, Dockge is deliberately compose-first — every stack it manages is a real compose file on disk in a directory you control, so there is no lock-in and no hidden state. You can edit a file in Dockge or in your own editor and the two stay in agreement. The container talks to the Docker daemon on the host through the mounted socket and shells out to `docker compose`, which is why two things in this stack are load-bearing. First, the Docker socket is mounted read-write, because Dockge starts and stops containers rather than only reading their state. Second, the stacks directory is mounted at the exact same path inside and outside the container, because Dockge writes compose files with host paths and then hands them to the daemon. The real caveat is security: a container holding the Docker socket has root-equivalent control of the host, and Dockge has no authentication until you create the first admin account. So this stack is built to sit behind the reverse proxy at `dockge.example.com` with nothing bound to the host directly, and you should create that admin account the moment it boots. The data Dockge owns — its settings and database — lives in the `dockge-data` volume, while your managed stacks live in the directory you chose.
Requirements
Before you start
- Docker 24+ and Docker Compose v2 on the host — Dockge drives the local Docker installation.
- Access to the Docker socket at `/var/run/docker.sock`. This grants root-equivalent control of the host; see the security notes below.
- A host directory for your stacks (default `/opt/stacks`), mounted at the same path inside the container.
- 512 MB RAM is comfortable for Dockge itself; the stacks it launches need their own resources on top.
Deploy
How to deploy
- Create the stacks directory on the host first, for example `sudo mkdir -p /opt/stacks`, and set `STACKS_DIR` in `.env` if you want a different path.
- Start the stack: `docker compose up -d`.
- Open `https://dockge.example.com` and create the first admin account right away — Dockge has no login until that account exists.
- Use "Add Stack" to create a new compose project, or use "Scan" to import compose files already present in the stacks directory.
- To adopt an existing project, move its `compose.yaml` into a subfolder of the stacks directory and let Dockge scan it.
Errors
Common errors & fixes
Dockge starts but reports "permission denied" talking to Docker, or shows no containers.
The container cannot use the Docker socket. Confirm `/var/run/docker.sock:/var/run/docker.sock` is mounted read-write (not `:ro` — Dockge has to start and stop containers) and that the socket exists on the host.
Stacks created in Dockge fail with "no such file or directory" when Compose runs.
The stacks directory is not mounted at the same path inside and outside the container. Dockge writes compose files with host paths and then runs `docker compose` against them, so the in-container path must equal the host path. Mount it as `/opt/stacks:/opt/stacks`, not onto a different target.
Containers started outside Dockge do not appear in the UI.
Dockge manages compose projects whose files live under its stacks directory. Move the `compose.yaml` of a project into the stacks directory and click "Scan", or recreate the stack through the UI.
The web UI is reachable on the LAN and anyone can drive it.
Dockge has no authentication until the first admin account is created, and that account controls Docker on the host. Do not publish port 5001 directly; keep it behind the reverse proxy, ideally with an extra auth layer, and create the admin account on first boot.
Limitations
Honest limitations
- Mounting the Docker socket gives Dockge, and anyone who reaches it, root-equivalent control of the host. Treat the Dockge URL like root SSH.
- Dockge manages compose projects living in its stacks directory. It is not a Portainer-style manager for arbitrary pre-existing containers, images, or networks.
- Single host by default: it drives the local Docker daemon (or one connected agent), not a Swarm or Kubernetes cluster.
- No built-in TLS and no multi-tenant roles: access is one shared admin login plus whatever the reverse proxy adds.
FAQ
Frequently asked
Why does Dockge need read-write access to the Docker socket?+
Its entire purpose is to create, start, stop, and update compose stacks, which means issuing write commands to the Docker daemon. A read-only socket would let it look but not act, leaving the UI inert. The cost of that access is that it is root-equivalent on the host.
Is mounting `/var/run/docker.sock` safe?+
It is the standard way to give a container control of Docker, but it is powerful: any process with the socket can launch a privileged container and take over the host. Keep Dockge off the public internet, put it behind a reverse proxy with authentication, and limit who can reach it.
Why must the stacks directory use the same path inside and outside?+
Dockge stores each stack as a real compose file and runs `docker compose` against it. The daemon resolves bind-mount and build paths as host paths, so if the container path and host path differ, those mounts break. Mapping `/opt/stacks:/opt/stacks` keeps them identical.
Can Dockge manage another machine?+
Yes, through its agent feature: run a Dockge agent on the remote host and connect it from the UI. This compose runs a single instance against the local socket; adding agents is done later inside Dockge.
What happens to my stacks if I remove or update Dockge?+
Nothing. The stacks are ordinary compose projects owned by the host Docker daemon, independent of the Dockge lifecycle. Removing Dockge leaves them running, and the compose files stay in the stacks directory.
Related