Why Dokploy is amazing (a love letter, with footnotes)
I moved this site from 'it works on my machine' to 'git push deploys it' in an afternoon, on my own server, without writing a single line of Traefik config by hand. Here is what Dokploy gets right, and the footnotes I wish I had read first.
I like owning my infrastructure, and I dislike maintaining it. For years the compromise was a VPS with a hand-written docker-compose.yml, an nginx config I was afraid to touch, and a deploy script named deploy2-final.sh. This week I replaced all of it with Dokploy, and I am a little bit in love. This is the love letter. The footnotes are at the end, and they matter.
What it is
Dokploy is an open-source, self-hosted deployment platform: think Heroku or Vercel, except it runs on your machine. Under the hood it is Docker Swarm for running things, Traefik for routing and TLS, and a Postgres database for its own state. You install it with one command on a fresh server and get a web UI with projects, environments, applications, databases, Compose stacks, logs and backups.
curl -sSL https://dokploy.com/install.sh | shFive minutes later you have a control panel and a reverse proxy that already knows how to obtain certificates.
What I run on it
This site. It is a Next.js application packaged as a Docker image. Dokploy does not build it; it pulls it. The application is of type "Docker", pointed at a private image on GitHub's container registry, with a token that can only read packages. That is the whole configuration: an image name, a registry credential, a port and a domain.
I like that split. The build happens where the code lives, the server only runs what was built.
The deploy loop
Here is what happens when I push to main:
-
GitHub Actions runs lint and type checks.
-
It builds the Docker image and pushes it to the registry, tagged
latestand with the commit SHA. -
It calls one endpoint on my Dokploy instance:
curl -X POST "$DOKPLOY_URL/api/application.deploy" \ -H "x-api-key: $DOKPLOY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"applicationId":"..."}' -
Dokploy pulls the new image, starts the new container, waits for the Docker health check, and swaps traffic over.
About three minutes from git push to the new version being live. Rolling back is changing the image tag from latest to sha-<previous commit> and clicking deploy. No build, no surprise.
The API is the killer feature
I did not create the application, the domain or the registry credential in the UI. I did it with three curl calls, because Dokploy exposes everything through an API authenticated by a single x-api-key header.
The OpenAPI document is served by the instance itself, which is how I found the exact request shapes without guessing:
curl -s -H "x-api-key: $DOKPLOY_TOKEN" \
"$DOKPLOY_URL/api/settings.getOpenApiDocument" > api.jsonSix hundred endpoints. Applications, domains, registries, SSH keys, backups, container logs, Docker volumes, Traefik config. If the UI can do it, the API can do it, and that means your infrastructure can be a script in a repository instead of a sequence of clicks you will forget.
Domains and TLS without fighting Traefik
Every application gets a Domains tab: hostname, port, HTTPS on or off, and how to get the certificate. The default is Let's Encrypt. In my case the hosting provider already supplies certificates for my domains, so I set the certificate type to none and let a small cron copy the provider's certificates into Traefik's dynamic configuration. Dokploy did not get in the way; it generates its own Traefik files per application and leaves mine alone.
That is the thing I keep noticing: Dokploy is opinionated about the happy path and quiet about the rest. When I needed to accept the PROXY protocol on the entry points (the provider's edge speaks it), I edited traefik.yml, restarted the container, done.
Things I love, in no particular order
- A mental model that fits in one sentence: project, environment, application, domain.
- Logs and container health one click away, without SSH.
- Private registries as first-class citizens.
- Compose stacks for the things that are not a single container.
- Backups to S3-compatible storage for the databases it manages.
- No lock-in. It is Docker and Traefik underneath. If Dokploy vanished tomorrow, my containers would keep running and I would know exactly how they are wired.
- It is fast, and it stays out of the way.
Footnotes
Now the part I wish someone had told me.
-
The dashboard listens on port 3000, and that port is not meant to be public. On a server behind a provider NAT, it is not even reachable. The right answer is an SSH tunnel, or publishing the dashboard through Traefik on a dedicated hostname with HTTPS. I did both; the tunnel is what I actually use.
-
PROXY protocol is off by default. If your provider's edge speaks it (mine does), Traefik will reject every connection until you enable
proxyProtocolon the entry points. Symptom: the site times out while every container looks healthy. -
The UI can overwrite hand-written Traefik files. The per-application files are Dokploy's; keep your own additions in separate dynamic config files with distinctive names, and keep a copy in git.
-
There is no artifact store. Dokploy is not a CI server. The image is the artifact, and it lives in your registry. That is the right design, but do not look for a "builds" tab.
-
Right after a VM reboot, you get a minute of "Oops, something went wrong". Dokploy starts before its Postgres is ready. It recovers on its own; just do not start debugging in that window like I did.
-
Private registry on GitHub means a classic token. Fine-grained personal access tokens do not work with the container registry. A classic token with only
read:packagesis all Dokploy needs.
Versus the others
- Coolify is the other big name, and it is excellent. It does more (more templates, more integrations) and the UI is busier for it. If you want a one-click marketplace for forty self-hosted apps, Coolify. If you want a calm control panel for your own applications, Dokploy.
- CapRover is older and very stable, with its own CLI-driven flow. It felt like a tool from a slightly earlier era of Docker; still a fine choice.
- Dokku is the minimalist: no UI at all, Heroku-style
git push. Wonderful if you live in a terminal and never want to explain the setup to anyone else.
I have used all three at some point. Dokploy is the first one where I did not feel the urge to peek under the hood every day.
Verdict
Own your server, and let something sane run it. Dokploy is that something for me right now: one command to install, an API for everything, and a Traefik that I no longer have to write by hand. Read the footnotes first, and the love letter writes itself.