Dokploy Core Infrastructure#
Overview#
Dokploy's core infrastructure consists of three internal services — Redis, Postgres, and Traefik — provisioned as Docker Swarm services or standalone containers on the host. All join a single overlay network named dokploy-network for DNS-based service discovery . Redis provides job queue persistence; Postgres is the application database; Traefik is the reverse proxy/TLS terminator.
The infrastructure is bootstrapped in two phases:
- Install time —
install.shcreates the Swarm, network, secrets, and base services. - Application boot —
setup.ts(run inside thedokploycontainer on every start) idempotently reconciles each service's Docker Swarm spec.
Install Script (install.sh)#
Source: apps/website/public/install.sh
The canonical install command is curl -sSL https://dokploy.com/install.sh | sh. The script performs these steps in order :
- Preflight — asserts root, Linux, and that ports 80, 443, 3000 are free .
- Docker install — installs Docker
28.5.0viaget.docker.com; holds packages withapt-markto prevent unintended upgrades . - Swarm init — calls
docker swarm init --advertise-addr <ip>; auto-detects IP from private interface, falling back to public IP . Custom CIDR and extra swarm args can be passed viaDOCKER_SWARM_INIT_ARGS. - Network — creates
dokploy-networkas an attachable overlay . - Secrets — generates random credentials with
openssl randand stores them as Docker Secrets (dokploy_postgres_password,dokploy_auth_secret) . - Postgres service —
docker service create ... postgres:16with thedokploy-postgresvolume mounted at/var/lib/postgresql/data. - Dokploy app service —
docker service create ... dokploy/dokploy:<VERSION>with Docker socket and/etc/dokploybind-mounted . - Traefik — started as
docker run --restart always traefik:v3.6.7and then attached todokploy-networkviadocker network connect.
Proxmox LXC is auto-detected and --endpoint-mode dnsrr applied to services; can also be forced via ENDPOINT_MODE=dnsrr .
Updating reuses the same script with sh -s update, which calls docker service update --image <new_image> dokploy .
Key evolution:
- Volume names were renamed in PR #3032 from opaque names (
redis-data-volume) to descriptive names (dokploy-redis,dokploy-postgres); the install script was updated to match in PR #89 . - LXC
--endpoint-mode dnsrrsupport was added in PR #109 .
Application Boot: setup.ts#
Source: apps/dokploy/setup.ts
This script runs inside the Dokploy container before the main server process and idempotently provisions each service. It tries to update existing services first; if not found, creates them. The sequence is :
setupDirectories()
createDefaultMiddlewares()
initializeSwarm()
initializeNetwork()
createDefaultTraefikConfig()
createDefaultServerTraefikConfig()
docker pull traefik:v<TRAEFIK_VERSION>
initializeStandaloneTraefik()
initializeRedis()
initializePostgres()
Key setup files in packages/server/src/setup/:
| File | Function | Service |
|---|---|---|
setup.ts | initializeSwarm(), initializeNetwork() | Swarm + dokploy-network overlay |
redis-setup.ts | initializeRedis() | dokploy-redis Swarm service (redis:8, volume dokploy-redis) |
postgres-setup.ts | initializePostgres() | dokploy-postgres Swarm service (postgres:16, volume dokploy-postgres) |
traefik-setup.ts | initializeStandaloneTraefik() / initializeTraefikService() | dokploy-traefik container or Swarm service |
All three internal services are pinned to manager nodes (node.role==manager) and join dokploy-network .
Redis in development: Port 6379 is published in host mode only when NODE_ENV === "development" . Production Redis is not exposed on any host port.
Server Runtime Boot: server.ts#
Source: apps/dokploy/server/server.ts
After setup, the main server performs its own initialization chain on startup (lines 61–76), only for self-hosted (non-cloud) deployments:
createDefaultMiddlewares()— writes Traefik middleware YAMLinitializeNetwork()— ensuresdokploy-networkexistsinitCronJobs()— Docker cleanup and backup cron schedulesinitSchedules()— user-defined recurring schedules from DBinitCancelDeployments()— resets anystatus=runningdeployments from before the restartinitVolumeBackupsCronJobs()— volume backup schedulessendDokployRestartNotifications()— notifies configured channelsstartDeploymentWorker()— starts the in-memory deployment queue worker (dynamically imported)
Deployment Queue#
Sources: queueSetup.ts, in-memory-queue.ts, deployments-queue.ts
Dokploy uses a custom in-memory queue (not BullMQ/Redis) for deployment jobs in self-hosted mode . The queue design:
- Per-partition concurrency — jobs are partitioned by
serverId; the local server uses theLOCAL_PARTITIONkey. Each partition runs up toconcurrencyjobs simultaneously . - Per-group FIFO — jobs for the same application or compose project never run in parallel; they serialize within their group .
- Concurrency is DB-driven — resolved via
resolveBuildsConcurrency()from the settings table . - Cloud uses a no-op queue — cloud deployments run directly in the background, bypassing the queue entirely .
The redis-connection.ts file defines a redisConfig pointing to host dokploy-redis (or REDIS_HOST env var) but is a legacy artifact; the in-memory queue does not use it. BullMQ (5.67.3) remains in package.json but the deployment queue has migrated away from it.
Stuck queue workaround: If a deployment is stuck in running state (e.g., after an OOM kill), the in-memory queue state is lost when the process exits. On instances that previously used BullMQ, legacy Redis keys (bull:deployments:*) may still be present and must be cleared manually :
TASK_ID=$(docker exec $(docker ps -q -f name=dokploy-redis) redis-cli LRANGE 'bull:deployments:active' 0 -1 | head -1)
docker exec $(docker ps -q -f name=dokploy-redis) redis-cli LREM 'bull:deployments:active' 0 "$TASK_ID"
docker exec $(docker ps -q -f name=dokploy-redis) redis-cli DEL "bull:deployments:$TASK_ID"
A UI option "Clean all deployment queue" was added in PR #3625 but only cancels pending jobs; orphaned active jobs may still require a service restart or manual cleanup . On server restart, initCancelDeployments() resets any remaining status=running records in Postgres .
Health Checks & Admin Controls#
The checkInfrastructureHealth tRPC procedure queries Postgres, Redis, and Traefik health and is exposed in the admin settings UI . Redis and Postgres health are verified by exec-ing redis-cli ping and pg_isready inside the running containers .
Services can be restarted from the admin settings UI via reloadServer, reloadTraefik, and reloadRedis tRPC mutations . These are no-ops on Dokploy Cloud.
Key File Index#
| File | Purpose |
|---|---|
apps/website/public/install.sh | One-shot install: Swarm, network, secrets, services |
apps/dokploy/setup.ts | Pre-boot service provisioner |
packages/server/src/setup/redis-setup.ts | Redis Swarm service spec |
packages/server/src/setup/postgres-setup.ts | Postgres Swarm service spec |
packages/server/src/setup/setup.ts | Swarm + network initialization |
apps/dokploy/server/server.ts | Runtime boot orchestration |
apps/dokploy/server/queues/in-memory-queue.ts | In-memory deployment queue implementation |
apps/dokploy/server/queues/queueSetup.ts | Queue initialization and worker start |
apps/dokploy/server/queues/deployments-queue.ts | Deployment job processor |