All articles
fastapidockerdokploy

Deploying a FastAPI Backend on DigitalOcean with Dokploy and Docker

A practical production deployment setup for FastAPI using Docker and Dokploy on a DigitalOcean VPS, with PostgreSQL, HTTPS, and operational hardening.

Kazi Efazul Karim
Kazi Efazul Karim
•4 min read
Deploying a FastAPI Backend on DigitalOcean with Dokploy and Docker

I recently moved my backend deployment from “works on my machine” to a production setup on a DigitalOcean VPS using Docker and Dokploy.

The goal was simple:

  • clean, repeatable deployments
  • low operational cost
  • room to scale later

The result is a practical stack that runs the API, PostgreSQL, HTTPS, and backups in a way that is easy to operate and maintain.

FastAPI + Dokploy + Docker deployment architectureFastAPI + Dokploy + Docker deployment architecture

Why I chose Dokploy#

I wanted something lighter than Kubernetes, but more structured than manually SSH’ing into a server and running everything by hand. Dokploy fit that middle ground.

It gives:

  • GitHub-based deployments
  • service management
  • domain + SSL handling
  • backups
  • a clean dashboard

Since I already had Dockerized services, Dokploy felt like the natural orchestration layer.

The architecture ended up being:

  • a single DigitalOcean VPS
  • Dokploy as the deployment platform
  • Docker containers for the API and PostgreSQL
  • HTTPS handled through Dokploy’s reverse proxy (Traefik)
  • GitHub as the source of truth

Step 1: Prepare the application for production#

Before deploying anything, I hardened the backend for production.

Main changes:

  • slim Docker image
  • non-root runtime user
  • HEALTHCHECK
  • startup script that runs migrations and then starts Gunicorn with Uvicorn workers
  • logging to stdout
  • TrustedHostMiddleware
  • secure cookies in production
  • ALLOWED_HOSTS
  • reusable outbound HTTP client
  • documented .env.example

These matter because deployment failures are often app-readiness issues, not VPS issues.

Step 2: Push the latest code to GitHub#

Dokploy deploys what is pushed, not what exists only locally.

So I made sure all production hardening changes were committed and pushed before server setup.

Step 3: Provision the VPS#

I used a 4 GB Ubuntu VPS in Singapore. That gave enough headroom for:

  • app container
  • PostgreSQL container
  • Dokploy
  • reverse proxy overhead

After running Dokploy’s installer, I got:

  • Docker
  • Docker Swarm support
  • Traefik for routing/TLS
  • Dokploy dashboard (initially on port 3000)

Step 4: Configure DNS#

I pointed a subdomain to the VPS with an A record.

This is critical because Let’s Encrypt issuance depends on correct DNS resolution and HTTP reachability.

Step 5: Add PostgreSQL inside Dokploy#

Instead of host-level PostgreSQL, I created PostgreSQL as a Dokploy-managed service.

For the internal connection string, I explicitly used:

  • internal hostname/network routing
  • sslmode=disable

That setting only affects DB traffic inside the private network and is separate from public HTTPS.

Step 6: Deploy the API service#

In Dokploy, I created a GitHub-connected Docker app and pointed it to:

  • repository
  • main branch
  • Dockerfile build
  • internal app port

Then I added environment variables based on .env.example:

  • production mode
  • database credentials
  • JWT secret
  • API keys
  • allowed hosts
  • frontend origin
  • base URL

The startup script handled migrations automatically on boot.

Step 7: Enable HTTPS#

Once DNS and ports were correct, Traefik handled TLS issuance and routing.

Important detail: the app container still listens on internal HTTP. HTTPS is terminated at Traefik.

Deployment request flow from browser to FastAPI containerDeployment request flow from browser to FastAPI container

Step 8: Verify the deployment#

I verified with a health endpoint, not /.

A successful verification means:

  • HTTPS works
  • domain resolves correctly
  • container is running
  • /health returns success

Lessons learned#

1) App readiness comes first#

Docker alone is not production readiness. Startup behavior, migrations, logging, host validation, and env hygiene matter just as much.

2) Internal DB SSL and external HTTPS are different layers#

  • DB SSL settings apply to database connectivity
  • HTTPS applies to public web traffic

They solve different problems.

3) DNS and ports are common failure points#

When TLS fails, usual causes are:

  • DNS not propagated
  • port 80 blocked
  • domain not properly attached
  • wrong internal target port

4) 4 GB VPS is a practical baseline#

It’s enough for a small production backend stack without premature complexity.

Final architecture#

  • DigitalOcean VPS: compute
  • Dokploy: deployment manager
  • Docker: runtime
  • PostgreSQL container: database
  • Traefik: SSL + routing
  • GitHub: source and deployment trigger
  • Health endpoint: operational check

Closing thoughts#

This setup feels production-grade without being heavy. For a solo dev or small team, it is a practical path: harden the app, containerize it, deploy with Dokploy, and keep operations simple.

Share this article

Found this helpful? Share it with your team or engineering network.