Dokploy Best Practices
Apply these rules when deploying or reviewing applications, databases, Docker Compose
stacks, domains, or infrastructure managed by Dokploy.
Dokploy is a self-hostable PaaS that orchestrates Docker Swarm behind a Traefik
reverse proxy, with a PostgreSQL + Redis control plane and a Next.js UI. Most
behaviors (zero downtime, rollbacks, domains) are thin wrappers over Swarm and Traefik
primitives — understanding both explains most pitfalls.
Core mental model
- A Service is one app/database/compose stack. Services live in an
Organization → Project → Environment → Service hierarchy. Use Environments
(production, staging) for isolation; never mix prod and staging in one environment.
- Variables cascade: project → environment → service, each level overriding the last.
Put shared secrets at project level, stage-specific values at environment level.
Reference with
${{project.VAR}}, ${{environment.VAR}}, ${{VAR}}.
- Applications route via Traefik file provider (hot-reload, no redeploy for domain
changes). Docker Compose / templates route via Traefik labels (redeploy required
for any domain change). This single distinction explains most "domain not working" 404s.
Golden rules
- Never build on the production server for real workloads. Nixpacks/Buildpack builds
are RAM/CPU heavy and can freeze the server. Build + push images in CI/CD (or a dedicated
build server) and deploy by image. See deployment-and-builds.md.
- Listen on
0.0.0.0, not 127.0.0.1. The #1 cause of Bad Gateway, especially Vite/
Astro/Vue. Match the domain's container port to the app's real port.
- Zero downtime needs a health check +
start-first. Without a /health endpoint and
Swarm update config, Swarm stops the old container before the new one is ready → Bad Gateway.
- Persist data in named volumes or
../files, never absolute host paths. Absolute paths
and repo-relative mounts get wiped on each git clone redeploy. Only named volumes can
be backed up by Volume Backups.
- Use
expose, not ports, for domain-routed Compose services. ports publishes to the
host and causes conflicts; Traefik routes over the internal network.
- Harden the host: Docker bypasses UFW. Container-published ports stay public despite UFW.
Use
ufw-docker or the VPS provider firewall.
Quick reference
Server & install baseline
- Minimum 2 GB RAM / 30 GB disk; more if you build on the server. Ports 80, 443, 3000
must be free (install fails otherwise). Supported: Ubuntu/Debian, Fedora, CentOS.
- Install:
curl -sSL https://dokploy.com/install.sh | sh. Pin versions with
DOKPLOY_VERSION. Update with ... | sh -s update.
- Secure before exposing: configure a domain with HTTPS, then disable
ip:port access
via docker service update --publish-rm "published=3000,target=3000,mode=host" dokploy.
- Avoid disk exhaustion (causes DB recovery mode / UI lockout): schedule
docker system prune jobs and enable Docker Cleanup.
When stuck
Most failures fall into a few buckets — domain/Traefik, mounts, Swarm health, or disk.
See the Troubleshooting section of platform-ops-security.md
for symptom → cause → fix tables (Bad Gateway, 404 on compose/templates, empty mounts,
UI inaccessible, Swarm init failure).
References
- deployment-and-builds.md — build types, production CI/CD, zero downtime, rollbacks, preview deployments, auto-deploy, patches, watch paths.
- domains-and-traefik.md — domain management, HTTPS/certificates, internal/strip path middlewares, www redirects, Traefik internals.
- docker-compose.md — Compose vs Stack, isolated deployments, manual Traefik labels, volumes, private registries.
- databases-backups-storage.md — databases, DB backups, volume backups, full-instance backups, S3 destinations, registries.
- platform-ops-security.md — multi-tenancy, variables, remote/build servers, scheduled jobs, server security, troubleshooting.
1---2name: dokploy-best-practices3description: Dokploy deployment and operations best practices. Use when the user deploys apps, databases, or Docker Compose stacks with Dokploy; configures domains, Traefik, Swarm health checks, CI/CD, backups, or webhooks; or troubleshoots Bad Gateway, 404, volume, database, or hardening issues.4---56# Dokploy Best Practices78Apply these rules when deploying or reviewing applications, databases, Docker Compose9stacks, domains, or infrastructure managed by Dokploy.1011Dokploy is a self-hostable PaaS that orchestrates **Docker Swarm** behind a **Traefik**12reverse proxy, with a **PostgreSQL** + **Redis** control plane and a Next.js UI. Most13behaviors (zero downtime, rollbacks, domains) are thin wrappers over Swarm and Traefik14primitives — understanding both explains most pitfalls.1516## Core mental model1718- A **Service** is one app/database/compose stack. Services live in an19 `Organization → Project → Environment → Service` hierarchy. Use Environments20 (`production`, `staging`) for isolation; never mix prod and staging in one environment.21- **Variables cascade**: project → environment → service, each level overriding the last.22 Put shared secrets at project level, stage-specific values at environment level.23 Reference with `${{project.VAR}}`, `${{environment.VAR}}`, `${{VAR}}`.24- **Applications** route via Traefik **file provider** (hot-reload, no redeploy for domain25 changes). **Docker Compose / templates** route via Traefik **labels** (redeploy required26 for any domain change). This single distinction explains most "domain not working" 404s.2728## Golden rules29301. **Never build on the production server for real workloads.** Nixpacks/Buildpack builds31 are RAM/CPU heavy and can freeze the server. Build + push images in CI/CD (or a dedicated32 build server) and deploy by image. See [deployment-and-builds.md](./deployment-and-builds.md).332. **Listen on `0.0.0.0`, not `127.0.0.1`.** The #1 cause of Bad Gateway, especially Vite/34 Astro/Vue. Match the domain's container port to the app's real port.353. **Zero downtime needs a health check + `start-first`.** Without a `/health` endpoint and36 Swarm update config, Swarm stops the old container before the new one is ready → Bad Gateway.374. **Persist data in named volumes or `../files`, never absolute host paths.** Absolute paths38 and repo-relative mounts get wiped on each `git clone` redeploy. Only **named volumes** can39 be backed up by Volume Backups.405. **Use `expose`, not `ports`, for domain-routed Compose services.** `ports` publishes to the41 host and causes conflicts; Traefik routes over the internal network.426. **Harden the host: Docker bypasses UFW.** Container-published ports stay public despite UFW.43 Use `ufw-docker` or the VPS provider firewall.4445## Quick reference4647| Goal | Approach | Reference |48| --- | --- | --- |49| Prototype fast | Nixpacks (default) or Railpack | [deployment-and-builds.md](./deployment-and-builds.md) |50| Production deploy | CI builds image → registry → deploy by image | [deployment-and-builds.md](./deployment-and-builds.md) |51| No-downtime deploy | Swarm health check + `FailureAction: rollback`, `Order: start-first` | [deployment-and-builds.md](./deployment-and-builds.md) |52| Domains / HTTPS / paths | Traefik file provider (apps) vs labels (compose) | [domains-and-traefik.md](./domains-and-traefik.md) |53| Multi-container app | Compose (`build` ok) vs Stack (registry images, `deploy.labels`) | [docker-compose.md](./docker-compose.md) |54| Persist & back up data | Named volumes + Volume Backups / DB Backups to S3 | [databases-backups-storage.md](./databases-backups-storage.md) |55| Auto-deploy | Webhook (push) or API (`application.deploy`) | [deployment-and-builds.md](./deployment-and-builds.md) |56| Scheduled tasks | App/Compose/Server/Dokploy-server cron jobs | [platform-ops-security.md](./platform-ops-security.md) |57| Scale out / cheap builds | Deployment servers + dedicated build server | [platform-ops-security.md](./platform-ops-security.md) |58| Harden the server | UFW + ufw-docker, SSH keys only, Fail2Ban | [platform-ops-security.md](./platform-ops-security.md) |5960## Server & install baseline6162- Minimum **2 GB RAM / 30 GB disk**; more if you build on the server. Ports **80, 443, 3000**63 must be free (install fails otherwise). Supported: Ubuntu/Debian, Fedora, CentOS.64- Install: `curl -sSL https://dokploy.com/install.sh | sh`. Pin versions with65 `DOKPLOY_VERSION`. Update with `... | sh -s update`.66- **Secure before exposing**: configure a domain with HTTPS, then disable `ip:port` access67 via `docker service update --publish-rm "published=3000,target=3000,mode=host" dokploy`.68- Avoid disk exhaustion (causes DB recovery mode / UI lockout): schedule69 `docker system prune` jobs and enable Docker Cleanup.7071## When stuck7273Most failures fall into a few buckets — domain/Traefik, mounts, Swarm health, or disk.74See the Troubleshooting section of [platform-ops-security.md](./platform-ops-security.md)75for symptom → cause → fix tables (Bad Gateway, 404 on compose/templates, empty mounts,76UI inaccessible, Swarm init failure).7778## References7980- [deployment-and-builds.md](./deployment-and-builds.md) — build types, production CI/CD, zero downtime, rollbacks, preview deployments, auto-deploy, patches, watch paths.81- [domains-and-traefik.md](./domains-and-traefik.md) — domain management, HTTPS/certificates, internal/strip path middlewares, www redirects, Traefik internals.82- [docker-compose.md](./docker-compose.md) — Compose vs Stack, isolated deployments, manual Traefik labels, volumes, private registries.83- [databases-backups-storage.md](./databases-backups-storage.md) — databases, DB backups, volume backups, full-instance backups, S3 destinations, registries.84- [platform-ops-security.md](./platform-ops-security.md) — multi-tenancy, variables, remote/build servers, scheduled jobs, server security, troubleshooting.