Portainer vs Dockge is the question almost everyone asks once they run their first server with a handful of Docker containers and get tired of typing docker compose up -d over SSH every time. Both are web interfaces for Docker, both are free, both run as a container themselves. But they follow two very different ideas. Portainer wants to be a complete control center for containers, images, volumes, networks, users and even Kubernetes. Dockge does exactly one thing: edit, start, stop and update Docker Compose stacks.
On 14 November 2026 we set up both as throwaway containers on our own server and measured them side by side: Portainer CE 2.45.3 (tag lts) and Dockge 1.5.0 (tag 1), both on Docker 29.9.3 running Ubuntu 24.04. We went through first-run setup, deployed the same nginx stack with each, checked where the compose file lands, measured memory, and then removed both completely. Four findings up front:
1. The Dockge image is 1.17 GB, the Portainer image 201 MB. At idle Dockge used 152 MiB of RAM, Portainer 22 MiB. The “lightweight” tool is the heavier one on disk and in memory.
2. Dockge stores every stack as a plain
compose.yamlin a folder on your server. Portainer stores it inside its own volume under/data/compose/1/. The path Docker records for it does not exist on the host at all.3. Portainer 2.45 can no longer be claimed by whoever opens the page first: it requires a setup token from the container logs and locks itself after five minutes without an admin account. Dockge has neither. First visitor becomes admin.
4. Dockge’s latest release is 1.5.0 from 30 March 2025. The repository has seen only a few commits since. Portainer shipped four releases between September and October 2026 alone.

Portainer vs Dockge: what is what?
Before we measure, a quick introduction to both candidates. Both talk to Docker through the same interface, the Docker socket /var/run/docker.sock. Through that file any tool controls the Docker daemon, exactly like the docker command line does. What each of them builds on top is very different.
Portainer has been around since 2016 and, with roughly 38,800 GitHub stars, is the best-known Docker UI there is. There is a free Community Edition (CE) under the Zlib license and a paid Business Edition with features like finer-grained access control and support. Portainer shows you everything Docker knows about: containers, images, volumes, networks, secrets, logs, stats, a console into the container. On top of that come users and teams, templates for ready-made apps, Git integration for stacks, and managing several servers through an agent. Portainer can also manage Docker Swarm and Kubernetes. It is a tool for everything.
Dockge comes from Louis Lam, the developer of Uptime Kuma, and appeared at the end of 2023. It has around 24,800 stars and is MIT-licensed. Dockge is deliberately small: at its core it only knows stacks, meaning Docker Compose projects. You see a list of your stacks, click one, and get a YAML editor on the left and the live output of docker compose on the right. Buttons for start, stop, restart and update, a terminal into the containers, done. You cannot manage images, volumes or networks individually in Dockge. Since version 1.4 one Dockge instance can connect other Dockge instances as “agents”, so you can run several servers from one interface.
If you are not sure what a compose stack actually is: our Docker Compose example explains it with a real project and six pitfalls we measured ourselves. And if you are just starting out, read What is Docker? first.
Our test setup
We did not want to copy screenshots from documentation. We wanted to use both tools the way a beginner would, and measure while doing it. It mattered to us that the tests did not touch any real service on the server. So both UIs only listened on 127.0.0.1 on ports nobody else uses, and every test container got the prefix pvd-.
We started Portainer the way the official guide shows, just with our own volume name and a local port:
docker run -d --name pvd-portainer \
-p 127.0.0.1:19443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v pvd_portainer_data:/data \
portainer/portainer-ce:lts
Dockge additionally needs a folder for the stacks. One detail that is easy to miss: the path must be identical inside and outside the container, because Dockge calls docker compose through the socket and Docker then resolves the paths on the host.
docker run -d --name pvd-dockge \
-p 127.0.0.1:15001:5001 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp/pvd/data:/app/data \
-v /tmp/pvd/stacks:/tmp/pvd/stacks \
-e DOCKGE_STACKS_DIR=/tmp/pvd/stacks \
louislam/dockge:1
In practice you would use a fixed folder like /opt/stacks. We did first-run setup and stack creation not by clicking, but through each program’s own interface: Portainer’s REST API and Dockge’s Socket.IO connection, which is what its web UI uses too. That let us time things precisely and record every response verbatim.
Installation: image size and startup time
The first difference shows up during the download, and it points in a direction many people do not expect.
| Portainer CE 2.45.3 | Dockge 1.5.0 | |
|---|---|---|
| Image size | 201 MB | 1.17 GB |
| Image built on | 2026-10-21 | 2025-03-30 |
| Download (our data center) | 2.1 s | 8.8 s |
| Until the UI responds | 0.4 s | 1.2 s |
| Written in | Go | Node.js (TypeScript) |
| License | Zlib (CE) | MIT |
Portainer is a single Go binary. Dockge ships a complete Node.js runtime, the Docker CLI, the Compose plugin and a frontend. That is why the image is almost six times larger. On a server with a 20 or 40 GB disk that is no drama, but on a small Raspberry Pi with a tight SD card you will notice it.
Startup time is a non-issue for both. After 0.4 and 1.2 seconds respectively, the UI was already returning HTTP 200.
First-run setup: setup token versus “first come, first served”
This was the most surprising finding of the test. Both tools ask for an admin account on first visit. The interesting question is: who is allowed to create that account?
Portainer has tightened this in recent versions. Our first attempt to create an admin account through the API failed with:
403 Invalid or missing setup token. Provide the X-Setup-Token header
with the token printed in the server logs at startup.
The token is printed in the container logs at startup:
docker logs pvd-portainer 2>&1 | grep setup_token
setup_token=2823124d2d60…
Paste it into the setup screen, or send it in the X-Setup-Token header.
Start with --no-setup-token to disable.
Only someone with access to the logs, which means access to the server itself, can set Portainer up. With the token, our test password kurz was rejected first (“Password does not meet the requirements”, HTTP 400); a long password went through. After that we still had to add the local Docker environment as an “environment”. Only then did Portainer show all twelve containers on the server.
Portainer also has a time lock. We started a second Portainer container and did not set it up. Started at 08:02, by 08:07 the log said:
the Portainer instance timed out for security purposes, to re-enable
your Portainer instance, you will need to restart Portainer
After five minutes without an admin account, Portainer shuts the door. Annoying if you go grab a coffee in between, but exactly right: a freshly installed, unclaimed Portainer on the internet is a gift to attackers.
Dockge has neither token nor time limit. Our test password kurz was rejected here too (“Password is too weak”); a password with letters and digits went through. A second attempt to run setup again with another username correctly failed (“Dockge has been initialized”). But until that moment, whoever reaches the page first creates the admin account. In the setup source code we found only two checks: password strength and “is there already a user?”. There is no time lock.
In practice this means: never start Dockge with a port open to the internet and set it up later. Either bind the port to 127.0.0.1 and reach it through an SSH tunnel, or create the account in the same minute the container comes up.

Creating stacks: where does your compose file go?
For us this is the most important difference in Portainer vs Dockge, because it decides how dependent you become on the UI. We created the same small stack with both:
services:
web:
image: nginx:alpine
ports:
- "127.0.0.1:18080:80"
With Dockge the file ended up exactly where you would expect it:
/tmp/pvd/stacks/pvd-demo/compose.yaml
A perfectly normal folder with a perfectly normal compose.yaml. Docker recorded exactly that folder as the project’s working directory. You can SSH in at any time and work with the usual commands:
cd /tmp/pvd/stacks/pvd-demo
docker compose ps
# pvd-demo-web-1 running
Dockge and the command line see the same file. You can version it with Git, back it up with rsync or a backup tool, and get rid of Dockge any time without anything changing in your stacks.
With Portainer the file lands in its own data volume:
/data/compose/1/docker-compose.yml (inside volume pvd_portainer_data)
Docker stores the label com.docker.compose.project.config_files=/data/compose/1/docker-compose.yml on the container. But that path only exists inside the Portainer container. On the host, ls /data/compose/1 replied “No such file or directory”. If you want to edit the stack on the command line, you first have to pull the file out of the volume. And if you change it on the host anyway, you now have two truths: Portainer keeps showing its own version.
This matches something that comes up in forums again and again: stacks you started outside Portainer with docker compose are shown, but labeled “Limited”, and you cannot edit their file. Dockge handles this more gracefully. In our test, every compose project already running on the server showed up immediately in the stack list, clearly marked as “not managed by Dockge”. If the file lives in the stacks folder, Dockge takes it over completely.
One point in Portainer’s favor: it can pull stacks straight from a Git repository and optionally redeploy automatically when the repo changes (GitOps). Then it does not matter where Portainer keeps its copy, because the truth lives in the repo. Dockge cannot do that.

Day-to-day use: deploy, restart, update
For everyday operation we timed the typical actions.
| Action | Portainer | Dockge |
|---|---|---|
| Create and start a stack | API answered after 66 ms, container up after about 3 s | 2.4 s until “Deployed” |
| Restart the stack | via the UI | 0.5 s (“Restarted”) |
| Update (pull new image and restart) | “Pull and redeploy” | 2.8 s (“Updated”), with live output |
| See compose output live | no, result only | yes, just like a terminal |
Raw times are not the point. Both end up calling Docker, and Docker decides how long a pull takes. What matters more is what you see while it happens. Portainer works in the background and reports success or failure. In our test the API response came back after 66 milliseconds, but the container was only reachable about three seconds later. Dockge, on the other hand, streams the full output of docker compose up live into your browser, including pull progress and error messages. When a stack refuses to come up, that is worth gold.
A small convenience feature beginners love in Dockge: convert docker run to compose. You paste a docker run command from some guide and get a compose file back. We tried it with a typical command:
docker run -d --name uptime -p 3001:3001 \
-v uptime:/app/data --restart unless-stopped louislam/uptime-kuma:1
Result:
services:
uptime-kuma:
container_name: uptime
ports:
- 3001:3001
volumes:
- uptime:/app/data
restart: unless-stopped
image: louislam/uptime-kuma:1
volumes:
uptime:
third-party: true
name: uptime
Watch out for one detail: the volume is declared third-party: true. That means Compose expects the volume uptime to already exist. On a fresh server the start then fails. Just delete the third-party: true and name: uptime lines and Compose creates the volume itself. Also, the port has no 127.0.0.1: in front of it, so it is open on all interfaces. Why that is more dangerous than it looks is shown in our UFW firewall setup guide: Docker ports bypass UFW.
Portainer has different everyday strengths. You can run single containers without Compose, clean up images, delete unused volumes, create networks and view stats per container. If you often touch individual containers or have several users with different permissions, Dockge will not get you far.
Memory use: which one is actually lightweight?
Dockge is described almost everywhere as a “lightweight Portainer alternative”. We measured something else. After setup and one deploy each, with a good half minute at idle, docker stats showed:
| Memory | CPU at idle | |
|---|---|---|
| Portainer (set up) | 22.3 MiB | 0.04% |
| Portainer (never set up) | 20.1 MiB | 0.00% |
| Dockge (set up) | 152 MiB | 0.23% |
A look at the process list explains the difference. Inside Portainer there is exactly one process, the Go binary. Inside Dockge there were two Node.js processes, two esbuild processes and a leftover docker-compose process from the last deploy. Node.js alone already needs a few dozen megabytes.
So “lightweight” is true for Dockge’s interface, not its resource use. On a server with 2 GB of RAM, 150 MiB is noticeable. On a home server with 16 GB it does not matter. How much headroom a server needs otherwise is something we work out in How much RAM does a server need?.

What happens when the UI goes down?
A worry beginners often have: if I stop Portainer or Dockge, are my applications gone? We stopped both management containers while the test stacks were running.
dockge-stack HTTP 200
portainer-stack HTTP 200
Both stacks kept running, unbothered. That is because neither Portainer nor Dockge runs the containers themselves. They only tell Docker what to do. If the UI is gone, you lose the control panel, not the application. The difference again lies in the files: without Dockge you simply keep working in the stack folder from the command line. Without Portainer you first have to get into the volume to find your compose file again.
Security: both hold the master key
Whichever you choose: anyone who can use Portainer or Dockge has root on your server. Both need the Docker socket, and with access to the socket you can start a container that mounts the host’s entire file system. That is not a flaw in either program, it is the nature of Docker.
That leads to a few simple rules that apply to both:
- Do not expose it to the internet. Ideally bind the UI to
127.0.0.1and reach it through an SSH tunnel or a VPN like Tailscale or WireGuard. - If it has to be public, use HTTPS behind a reverse proxy and a strong password. Portainer ships a self-signed certificate on port 9443. Dockge only speaks HTTP, so its port 5001 should never be directly reachable.
- Turn off Portainer’s port 9000. In our test Portainer also answered unencrypted on port 9000 with HTTP 200, because we had published it. Just leave out
-p 9000:9000. - Bind ports in compose files to
127.0.0.1when the service should only be reachable through the reverse proxy.
There are still a few differences. Portainer has a permission system with users and teams (finer roles only in Business Edition); Dockge knows exactly one user. Portainer has a setup token and time lock; Dockge does not. In April 2026 a warning about a possible XSS issue in Dockge’s frontend was fixed in the repository, but there is no new release containing that fix. If you pull louislam/dockge:1, you still get the March 2025 state.
Maintenance and future: which one is still being developed?
This is the point we had underestimated beforehand. We checked both projects’ releases on 14 November 2026:
| Portainer | Dockge | |
|---|---|---|
| Latest release | 2.45.3 (2026-10-21) | 1.5.0 (2025-03-30) |
| Releases since September 2026 | 4 (2.39.8, 2.45.1, 2.45.2, 2.45.3) | 0 |
| Last commit in the repository | 2026-11-12 | 2026-10-23 (build pipeline change) |
| Last code change | ongoing | April 2026 (security and lint fixes) |
| Nightly builds | – | yes, nightly tag rebuilt daily |
| Company behind it | Portainer.io | solo developer plus community |
Dockge is not dead, but it is dormant. The concept is now so simple and stable that it keeps working without new releases. Because Dockge ultimately just calls docker compose, you would benefit from new Compose features as soon as the Compose plugin in the image is updated. But that only happens with a new release. The March 2025 image contains the March 2025 Compose.
Portainer, on the other hand, is actively maintained, has a company behind it and receives security updates. The price: Portainer promotes the Business Edition fairly visibly in the UI, and some features sit behind the paywall.
If you like Dockge but are unsure about maintenance, take a look at the newer tools heading in the same direction. Commonly mentioned are Komodo, Arcane and Dockhand. We did not measure them in this test, so this is just a pointer that they exist. The nice part about Dockge’s approach: because your stacks are plain files, you can switch later with no effort.
Portainer vs Dockge: all differences at a glance
| Portainer CE | Dockge | |
|---|---|---|
| Focus | Everything Docker, Swarm, Kubernetes | Docker Compose stacks only |
| Image size | 201 MB | 1.17 GB |
| RAM at idle (our measurement) | 22 MiB | 152 MiB |
| Where compose files live | inside the Portainer volume (/data/compose/N/) | regular folder on the host |
| Adopting existing stacks | limited (“Limited”) | yes, if the file is in the stacks folder |
| Manage single containers, images, volumes | yes | no |
| Live output on deploy | no | yes |
Convert docker run to compose | no | yes |
| Git integration / GitOps | yes | no |
| Users and permissions | yes (fine roles in Business) | one user |
| Multiple servers | Agent, Edge Agent | Dockge agents (since 1.4) |
| Setup protection | token from logs + 5-minute lock | none |
| Built-in HTTPS | yes (self-signed, port 9443) | no |
| Latest release | October 2026 | March 2025 |
| License | Zlib (CE), Business is paid | MIT |

Our recommendation: Portainer or Dockge?
There is no winner for everyone. The decision hinges on one question: do you want a UI that manages Docker, or one that edits your compose files?
Pick Dockge if:
- you run one or a few servers with compose stacks, typically a home server or small VPS,
- you want to keep owning the files and reach them via SSH, Git or backups,
- you want to see what happens during a deploy,
- you work alone and do not need user management,
- 150 MiB of RAM does not bother you.
Pick Portainer if:
- you want to manage individual containers, images, volumes and networks graphically,
- several people with different permissions need access,
- you want to roll out stacks from Git automatically,
- you use Swarm or Kubernetes,
- regular security updates matter to you,
- the server is short on RAM.
Running both at once works fine, by the way, and many people do exactly that. Dockge for the stacks, Portainer as an X-ray for everything else. Both talk to Docker over the same socket and do not get in each other’s way. Just never edit the same stack from both, or you are back to two truths.
And honestly: for many small servers the best UI is none at all. A folder /opt/stacks with one subfolder per app, each holding a compose.yaml, versioned with Git, plus docker compose up -d over SSH. That is exactly the structure Dockge creates itself, by the way. If you use it from day one, you can add Dockge later or remove it again any time. How to prepare the server properly for that is shown in Linux server setup.
How to install Dockge safely
If you go with Dockge, here is a compose file that avoids the pitfalls from our test: a fixed stacks folder with the same path inside and out, and a local-only port.
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
ports:
- "127.0.0.1:5001:5001"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
Put the file at, say, /opt/dockge/compose.yaml, start it with docker compose up -d and open it right away through an SSH tunnel:
ssh -L 5001:127.0.0.1:5001 user@your-server
# then in the browser: http://localhost:5001
Create the admin account immediately. Only after that, if at all, put a reverse proxy with HTTPS in front.
How to install Portainer safely
The safe Portainer variant looks similar. We leave out port 9000 and keep 9443 local:
services:
portainer:
image: portainer/portainer-ce:lts
restart: unless-stopped
ports:
- "127.0.0.1:9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
After startup, grab the setup token:
docker compose logs portainer | grep setup_token
Then open an SSH tunnel to port 9443, visit https://localhost:9443, paste the token, create the admin. Mind the five minutes. If they run out, docker compose restart portainer helps, and you get a new token.
One more tip if you ever want to move Portainer stacks to Dockge or the command line: the files live in the volume under compose/<number>/docker-compose.yml. A short throwaway container gets you there:
docker run --rm -v portainer_data:/d alpine find /d/compose -name '*.yml'
Limits of our test
To be honest: we tested both tools in one morning on one server, not over months of continuous use. The memory figures are snapshots after half a minute at idle with a single stack. With many stacks and open browser tabs, both will use more. We did not try the multi-server features (Portainer agent, Dockge agents) or the Business Edition. We removed every container, volume, network and image from the test afterwards. Nothing was left behind on the server.
Frequently asked questions
Is Dockge better than Portainer?
Not in general. Dockge is simpler and leaves your compose files as normal files on the server. Portainer can do far more, is more actively maintained and used less RAM in our measurement. For a home server with a few stacks Dockge is often nicer; for teams and larger setups, Portainer.
What is the main difference between Portainer and Dockge?
Portainer manages Docker as a whole: containers, images, volumes, networks, users, even Kubernetes. Dockge only manages Docker Compose stacks and stores them as compose.yaml in a folder of your choice. Portainer stores its stack files in its own volume instead.
Can I use Portainer and Dockge at the same time?
Yes. Both talk to the same Docker daemon through the Docker socket and do not interfere. But edit each stack in only one of the two tools, otherwise you end up with two different versions of the compose file.
Is Dockge still maintained?
As of 14 November 2026 the latest release is 1.5.0 from 30 March 2025. The repository has had security and maintenance commits since, most recently in October 2026, and nightly builds are produced daily. There has been no new stable release for over a year and a half. Dockge still works reliably because it just calls docker compose.
Is Portainer free?
The Community Edition (CE) is free and open source. There is also a paid Business Edition with extra features such as fine-grained access control and support. For your own server, CE is almost always enough.
How much RAM does Dockge need?
In our test Dockge used about 152 MiB at idle, Portainer about 22 MiB. Dockge runs on Node.js and keeps several processes alive. On small servers with 1 to 2 GB of RAM you should plan for that.
How do I move my Portainer stacks to Dockge?
Get the compose files out of the Portainer volume (compose/<number>/docker-compose.yml), create one folder per stack in Dockge’s stacks directory and save the file there as compose.yaml. Important: the folder name becomes the project name. If it matches the name in Portainer, Docker recognizes the running containers. Otherwise new containers are created and, unless you name your volumes explicitly, new volumes too.
Is it dangerous to expose Portainer or Dockge to the internet?
Yes. Whoever can use the UI effectively has root on the server through the Docker socket. Bind the port to 127.0.0.1 and use an SSH tunnel or VPN. If it must be public, only with HTTPS behind a reverse proxy, a strong password and ideally an extra layer of protection in front.
What is Portainer’s setup token?
In current versions, Portainer writes a random token to the container logs on first start. Only someone who knows that token can create the admin account. Without an admin account, Portainer locks itself after five minutes; restarting the container lifts the lock.
Can Dockge manage Kubernetes or Docker Swarm?
No. Dockge only knows Docker Compose on one or more servers (via Dockge agents). For Swarm or Kubernetes, Portainer is the right choice of the two.
Are there alternatives to Portainer and Dockge?
Yes, for example Komodo, Arcane, Dockhand or Yacht. If you use Podman instead of Docker, our Docker vs Podman comparison has notes on which UIs work there. And for many small servers, a folder of compose files plus SSH is perfectly enough.
Do I need Docker Compose on the server for Dockge?
No, the Compose plugin is bundled in the Dockge image. It is still handy to have Compose on the host as well, so you can operate the stacks from the command line in an emergency without Dockge.
Conclusion
In Portainer vs Dockge, the winner is the tool that fits the way you work. Dockge is the nicer interface for Docker Compose: it shows you live what is happening, converts docker run into compose and leaves your stacks as plain files on the server. In return it is surprisingly large, used seven times as much RAM as Portainer in our measurement, has no protection during first-run setup, and has not had a release since March 2025.
Portainer is the full control center, actively maintained, protects first-run setup with a token and time lock, and barely uses any memory. In return it hides your compose files in its own volume and is often more tool than pure compose users need.
Our own approach on our servers stays the plainest one: one folder per stack, compose files in Git, deploys over SSH. If we add a UI, it is Dockge, because we can remove it any time without anything changing in the stacks. How containers talk to each other once you have several stacks is explained in Docker networking explained.