Back to Blog
DevOps Docker Dokploy Cloud Costs

Dokploy & Docker: Self-Hosted PaaS on Cheap VPS

• 10 min read • Written by Marlon

TL;DR:

  • The Trap: Commercial PaaS platforms like Vercel, Render, or Heroku charge an 800% markup on standard compute; running two APIs, a worker, a database, and a cache rapidly climbs past $280/month while imposing strict execution time limits and memory caps.
  • The Architecture: Self-hosted PaaS using Dokploy or Coolify on commodity VPS instances (Hetzner, OVH, or DigitalOcean), leveraging multi-stage Docker builds, Traefik reverse proxy with automated Let’s Encrypt TLS, internal bridge networking, and rolling zero-downtime swaps.
  • The Business Impact: Cuts hosting costs by over 90% (down to $20–$25/month) while unlocking 4x more CPU and RAM, eliminating vendor lock-in, and preserving continuous Git-push automated delivery.

The Commercial PaaS Trap: Paying an 800% Convenience Tax

Paying three hundred dollars every month on commercial PaaS vendors to run a couple of web applications and a PostgreSQL database is not real scalability.

It is burning early-stage company runway out of operational inertia.

Platforms like Render, Heroku, and Vercel are magnificent tools for launching weekend prototypes. Running a git push and watching an application deploy in sixty seconds is an addictive developer experience.

However, the moment your product captures commercial traction and you provision a background queue worker, a Redis instance, and a staging environment, the financial reality sets in.

You are paying an 800% markup over raw compute pricing:

  • A basic 4GB RAM background container on managed PaaS costs $85/month.
  • A managed 2-core PostgreSQL database costs $100/month.
  • The same compute capacity on an enterprise European or US VPS provider like Hetzner costs under $6/month.

For a seed-stage startup striving to stretch runway ahead of a funding round, financing cloud vendor margins is an avoidable operational penalty.

You do not need an enterprise Kubernetes cluster to reclaim your cloud sovereignty.

With Dokploy, you achieve the exact same automated Git deployment experience on your own dedicated VPS for under $25 per month.

  1. STAGE 01 Webhook

    Git Push Trigger

    GitHub or GitLab fires a secure webhook to Dokploy on main branch commits, initiating isolated container builds.

  2. STAGE 02 BuildKit

    Multi-Stage Build

    Docker BuildKit compiles optimized production images with non-root security boundaries and cached dependency layers.

  3. STAGE 03 Traefik Ingress

    Traefik SSL Routing

    Traefik intercepts incoming traffic, provisions automated Let's Encrypt certificates, and routes traffic over internal Docker bridges.

  4. STAGE 04 Zero-Downtime

    Rolling Healthcheck Swap

    The new container passes healthcheck probes before Traefik shifts live traffic, gracefully terminating the old container.


Architectural Deep Dive: Dokploy vs Kubernetes vs Raw Docker

When evaluating self-hosted deployment strategies, engineering teams face three primary paths:

1. Raw Manual Docker with Shell Scripts (The Anti-Pattern)

Connecting via SSH and running docker stop && docker rm && docker run manually in production is fragile.

It causes guaranteed service downtime on every release, leaves credentials scattered across .bash_history files, and lacks automated rollback capabilities when a faulty container crashes on startup.

2. Full Kubernetes / K3s (The Overkill Trap)

Spinning up a 3-node Kubernetes cluster to deploy an MVP introduces staggering cognitive overhead.

Engineers spend 40% of their sprints writing Helm charts, debugging ingress controllers, and troubleshooting CNI networking bugs instead of shipping core product features.

3. Dokploy: The Pragmatic Sweet Spot

Dokploy installs directly onto a single VPS or dedicated bare-metal server via a single shell script.

It provides a modern web interface backed by Docker Compose and Traefik:

  • Automatic Traefik Service Discovery: Traefik dynamically inspects Docker container labels. When a new container spins up with traefik.http.routers.api.rule=Host('api.company.com'), Traefik configures TLS routing in real time without restarting the proxy.
  • Zero-Downtime Blue/Green Swaps: Docker starts the candidate container on an ephemeral internal port, verifies HTTP 200 healthcheck status, and updates Traefik’s routing table before gracefully shutting down the previous revision.
  • Internal Network Isolation: Database containers (PostgreSQL, Redis) bind to an internal Docker network bridge with zero exposed host ports. External attackers cannot port-scan your database from the public internet.

Financial Breakdown: Commercial PaaS vs Self-Hosted VPS

The unit economics for a standard production SaaS stack comprising a Next.js frontend, Node.js API, background queue worker, PostgreSQL database, and Redis cache:

Resource / LayerManaged PaaS (Vercel + Render)Self-Hosted VPS with DokployNet Monthly Savings
Web Frontend (Next.js / Astro)$20 / mo (Pro Team seat)$0 / mo (Runs in container)$20 / mo
Backend API (4GB RAM, 2 vCPU)$85 / mo (Dedicated Render tier)$0 / mo (Runs in container)$85 / mo
Background Worker (BullMQ / Inngest)$35 / mo (Standard worker tier)$0 / mo (Runs in container)$35 / mo
Managed PostgreSQL (10GB disk)$95 / mo (Render / Supabase Pro)$0 / mo (Docker volume with S3 backup)$95 / mo
Redis Cache (1GB RAM)$40 / mo (Upstash / Redis Cloud)$0 / mo (Docker Redis instance)$40 / mo
Total Monthly Cost$275 / month$22 / month (Hetzner CCX13, 8GB RAM)$253 / mo (92% Cut)

Over a twelve-month runway, this single architectural pivot keeps more than $3,000 USD of raw capital directly inside your startup’s bank account.


Code Comparison: Fragile Manual Script vs Production Dokploy Stack

Naive: Manual SSH Script with Downtime and Exposed Database Ports

# Naive Deployment Script: Exposed DB, hardcoded secrets, guaranteed application downtime
#!/usr/bin/env bash
ssh root@192.241.150.82 << 'EOF'
  cd /var/www/my-app
  git pull origin main

  # Problem 1: Service downtime! Shuts down container before new one is ready
  docker stop backend-api
  docker rm backend-api

  # Problem 2: Exposing database port 5432 directly to public internet!
  docker run -d --name postgres-db -p 5432:5432 -e POSTGRES_PASSWORD=rootpassword postgres:16

  # Problem 3: No healthcheck verification - if app fails, users get 502 bad gateway
  docker build -t backend-api .
  docker run -d --name backend-api -p 3000:3000 backend-api
EOF

Production: Declarative Dokploy Docker Compose with Internal Bridge & Traefik

# Production Docker Compose: Zero Public DB Exposure, Traefik TLS, Resource Limits
version: "3.8"

networks:
  dokploy-network:
    external: true # Managed Traefik ingress network
  internal-bridge:
    driver: bridge
    internal: true # CRITICAL: Completely denies public internet ingress to internal databases

services:
  backend-api:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    networks:
      - dokploy-network
      - internal-bridge
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres-db:5432/production_db
      - REDIS_URL=redis://redis-cache:6379
    deploy:
      resources:
        limits:
          cpus: "1.5"
          memory: 2048M # Prevents memory leaks from crashing the host OS
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/api/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 15s
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.backend.rule=Host(`api.coins5.dev`)"
      - "traefik.http.routers.backend.entrypoints=websecure"
      - "traefik.http.routers.backend.tls.certresolver=letsencrypt"
      - "traefik.http.services.backend.loadbalancer.server.port=3000"

  postgres-db:
    image: postgres:16-alpine
    restart: unless-stopped
    networks:
      - internal-bridge # ONLY connected to internal network; ZERO host ports exposed!
    environment:
      POSTGRES_DB: production_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 2048M

  redis-cache:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
    networks:
      - internal-bridge
    volumes:
      - redis-data:/data

volumes:
  postgres-data:
  redis-data:

Automated Nightly S3 Backup Script with AES Encryption

#!/usr/bin/env bash
# Automated Off-Site Encrypted Database Backup to Amazon S3 / Cloudflare R2
set -euo pipefail

TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/var/backups/postgres"
CONTAINER_NAME="postgres-db"
DB_NAME="production_db"
S3_BUCKET="s3://company-secure-db-backups/daily"

mkdir -p "${BACKUP_DIR}"

# 1. Stream atomic pg_dump, compress with gzip, and encrypt with OpenSSL AES-256
docker exec "${CONTAINER_NAME}" pg_dump -U postgres "${DB_NAME}" \
  | gzip \
  | openssl enc -aes-256-cbc -salt -pbkdf2 -pass "env:BACKUP_ENCRYPTION_KEY" \
  > "${BACKUP_DIR}/backup_${DB_NAME}_${TIMESTAMP}.sql.gz.enc"

# 2. Sync encrypted payload to off-site cloud storage via AWS CLI or Rclone
aws s3 cp "${BACKUP_DIR}/backup_${DB_NAME}_${TIMESTAMP}.sql.gz.enc" "${S3_BUCKET}/"

# 3. Clean local backups older than 7 days
find "${BACKUP_DIR}" -type f -mtime +7 -delete

echo "[BACKUP SUCCESS] Encrypted database backup committed to ${S3_BUCKET} at ${TIMESTAMP}"

Real-World Case Studies: Production Resilience on Lean VPS

Strategio (Startup Perú 2G Winner): Multi-App SaaS Stack on a Single VPS

Strategio powers AI business intelligence analytics for competitive retail companies.

  • The Problem: The team needed to run the main web portal, an asynchronous background data-scraping worker, a PostgreSQL database, and a Redis message queue. Deploying this on commercial PaaS would have quickly exceeded $300/month.
  • The Solution: We deployed Dokploy on a single Hetzner Dedicated Cloud VPS ($18/month). All backend services communicate through isolated Docker network bridges with automated Traefik SSL and nightly encrypted S3 database backups.
  • The Result: The entire platform has maintained 99.98% uptime across two years, serving analytics with zero vendor lock-in while keeping total infrastructure expenses under $20 USD/month.

NubaNutrición (nubanutricion.com): Decoupled Staging & Production on Under $30/Month

NubaNutrición integrates clinical dietary algorithms with patient management backends.

  • The Problem: The team required dedicated staging environments to test machine learning model updates without impacting live patient consultations, but commercial PaaS charged extra per environment.
  • The Solution: Using Dokploy’s multi-project workspaces on a single 16GB VPS, we provisioned isolated production and staging container stacks sharing a host server with strict resource boundaries.
  • The Result: The startup deployed rapid staging updates with zero interference to production, saving over $240/month in managed hosting markups.

Pre-Flight Checklist for Self-Hosted VPS Dokploy Migrations

Before migrating production workloads from commercial PaaS to a self-hosted Dokploy VPS, verify these five architectural gates:

  • Internal Network Isolation: Are databases (Postgres, MySQL, Redis) strictly confined to internal Docker bridges with zero exposed public host ports?
  • Automated Off-Site Backups: Is an automated cron job backing up database volumes, encrypting dumps via AES-256, and uploading payloads to AWS S3 or Cloudflare R2?
  • Docker Resource Limits Enforced: Does every container in docker-compose.yml declare explicit CPU and memory limits to prevent memory leaks from freezing the host?
  • HTTP Healthchecks Configured: Have you configured active healthcheck endpoints so Traefik only routes live traffic after containers successfully initialize?
  • Host Firewall Hardened (UFW): Are only ports 80, 443, and your non-standard SSH port open to the public internet on the host firewall?

Architectural Advisory

Self-hosting your applications on modern VPS instances is the most effective way to eliminate cloud waste and preserve capital without sacrificing modern Git-push developer velocity.

At Coins5, Marlon helps startups and businesses migrate away from overpriced PaaS platforms, configure hardened Docker deployment pipelines, and build resilient infrastructure that costs under $25/month.

If your team is looking to cut hosting costs by 90% or needs assistance architecting a rock-solid self-hosted deployment stack, schedule a 15-minute discovery call or connect directly on WhatsApp.

Tired of Paying Bloated PaaS Hosting Bills?

Let's architect your self-hosted Docker deployment stack on high-performance VPS in a concise 15-minute technical discovery call.

Marlon - Senior Architect
Author & Systems Architect

Marlon / Coins5

Senior Full Stack Developer & Cloud Architect. Building custom software and production MVPs with Clean Architecture, high-concurrency cloud design, and AI velocity.

Book 15m Call