Skip to main content

How to Migrate from Heroku to Dokku 2026

·OSSAlt Team
herokudokkumigrationpaasguide
Share:

How to Migrate from Heroku to Dokku 2026

Dokku was built as a mini-Heroku. Same buildpacks, same Procfile, same git push workflow — running on your own VPS. Of all the Heroku alternatives, Dokku has the smallest migration surface because it deliberately mimics Heroku's developer interface. The migration is the smoothest of any Heroku alternative, often completable in a single day.

TL;DR

If your app uses a Heroku-compatible buildpack and a Procfile, the Dokku migration is mostly: install Dokku on a VPS, create an app with the same name, migrate environment variables, migrate the database dump, add a Git remote, and push. The git push dokku main workflow is identical to git push heroku main.

Key Takeaways

  • Dokku supports all Heroku buildpacks (Node.js, Python, Ruby, Go, PHP, Java, etc.) without modification
  • Your Procfile works unchanged — web, worker, and release process types all work
  • Database migration uses standard pg_dump/pg_restore — no proprietary tooling
  • Dokku add-ons (postgres, redis, MongoDB, etc.) are separate plugins, but installation is one command
  • Let's Encrypt SSL is automated via a plugin — same as Heroku's ACM
  • Cost savings are typically 60-85% for production workloads

Why Dokku Over Other Heroku Alternatives

When Heroku eliminated its free tier and raised prices significantly, teams evaluated multiple migration targets: Render, Railway, Fly.io, Coolify, and Dokku. For teams with Heroku-specific workflows (buildpacks, Procfiles, config vars), Dokku offers the path of least resistance. Nothing in your app needs to change.

Coolify offers a broader feature set with a modern web UI and supports Docker Compose apps natively, making it a better choice for teams managing multiple app types. But if your entire stack is Heroku-buildpack-compatible apps, Dokku's CLI-first approach is simpler and lighter weight.

See the full roundup of open source Heroku alternatives if you want to compare deployment options across the ecosystem before committing.

Step 1: Provision a VPS

Dokku needs a VPS running Ubuntu 22.04 or 24.04. For a single app, a $6-10/month VPS (DigitalOcean, Hetzner, Linode, Vultr) is sufficient. For multiple apps or a production database, size up to $20-40/month depending on load.

Minimum requirements:

  • 1 vCPU, 1 GB RAM (for simple apps)
  • 2 vCPU, 2 GB RAM (recommended for production)
  • 20+ GB SSD storage

SSH in as root (or a sudoer) and run:

# On a fresh Ubuntu VPS (22.04+)
wget -NP . https://dokku.com/install/v0.34.8/bootstrap.sh
sudo DOKKU_TAG=v0.34.8 bash bootstrap.sh

# Set your domain
dokku domains:set-global yourdomain.com

# Add your SSH key
cat ~/.ssh/id_rsa.pub | dokku ssh-keys:add admin

The bootstrap script installs Docker, configures the Dokku user, and sets up the git receive hook. The entire install takes under 5 minutes on a modern VPS.

Step 2: Create App and Services

# Create app (same name as your Heroku app)
dokku apps:create myapp

# Install and create database
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git
dokku postgres:create myapp-db
dokku postgres:link myapp-db myapp

# Install and create Redis (if needed)
sudo dokku plugin:install https://github.com/dokku/dokku-redis.git
dokku redis:create myapp-redis
dokku redis:link myapp-redis myapp

When you link a service to an app, Dokku automatically sets the appropriate environment variable (DATABASE_URL, REDIS_URL) in your app's config. This mirrors how Heroku add-ons inject their connection strings. No manual configuration needed.

Dokku has official plugins for PostgreSQL, MySQL, MariaDB, MongoDB, Redis, Elasticsearch, and more. Browse the official plugin index at dokku.com/docs/community/plugins.

Step 3: Set Environment Variables

# Export from Heroku
heroku config -a myapp --shell > heroku-env.txt

# Set in Dokku (one by one)
dokku config:set myapp NODE_ENV=production
dokku config:set myapp SECRET_KEY=your-secret
dokku config:set myapp SMTP_HOST=smtp.example.com

# Or bulk set from the exported file
dokku config:set myapp $(cat heroku-env.txt | xargs)

One important difference: Heroku's DATABASE_URL will point to Heroku's database. After linking Dokku's postgres plugin, Dokku sets its own DATABASE_URL automatically. Remove the Heroku DATABASE_URL from your bulk import to avoid overwriting it.

Sensitive variables like API keys should be set individually rather than via a bulk export file that might be stored in your shell history or version control. Dokku stores all config vars securely in /home/dokku/myapp/ENV.

Step 4: Deploy

# On your local machine
cd your-project

# Add Dokku remote
git remote add dokku dokku@your-server:myapp

# Push to deploy
git push dokku main

Your Procfile works unchanged. Your buildpacks work unchanged. If your app already deploys to Heroku via git push, this command is the only change to your deployment workflow.

Dokku automatically detects buildpacks via the standard Heroku buildpack detection order. Node.js apps detected by package.json, Python by requirements.txt or Pipfile, Ruby by Gemfile, etc. If you use a custom buildpack, set it explicitly:

dokku buildpacks:set myapp https://github.com/heroku/heroku-buildpack-nodejs.git

Step 5: Set Up SSL

# Install Let's Encrypt plugin
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

# Configure email
dokku letsencrypt:set myapp email admin@yourdomain.com

# Enable SSL
dokku letsencrypt:enable myapp

# Auto-renewal
dokku letsencrypt:cron-job --add

This is equivalent to Heroku's Automatic Certificate Management (ACM). The plugin handles renewal automatically via a cron job. Certificate renewal is fully automated and requires no manual intervention.

Step 6: Set Up Domain

# Add custom domain
dokku domains:add myapp myapp.yourdomain.com

# Remove the default Dokku-generated domain if you don't need it
dokku domains:remove myapp myapp.yourdomain.com

Point your domain's DNS A record to your Dokku server's IP address. DNS propagation typically takes 5-30 minutes. Once propagated, Dokku's nginx will route traffic to your app automatically.

For multiple apps on the same server, each app gets its own subdomain or custom domain. Dokku's nginx handles virtual hosting for all apps on the server from a single IP.

Step 7: Migrate Database Data

# Export from Heroku
heroku pg:backups:capture -a myapp
heroku pg:backups:download -a myapp

# Import to Dokku Postgres
dokku postgres:import myapp-db < latest.dump

The postgres:import command accepts a pg_dump file and restores it to the linked database. Run this before your first deployment to ensure your app starts with production data. Verify the import worked by running a quick SQL check:

dokku postgres:connect myapp-db
# In psql:
\dt         -- list tables
SELECT COUNT(*) FROM users;   -- verify row counts

For large databases (10+ GB), consider importing during a maintenance window and using pg_restore -j 4 with parallel restore for faster imports. The Dokku postgres plugin wraps pg_restore internally, so for very large databases, you may want to connect directly with dokku postgres:connect and run pg_restore manually.

Heroku → Dokku Command Mapping

HerokuDokku
heroku createdokku apps:create
git push heroku maingit push dokku main
heroku config:setdokku config:set
heroku logs --taildokku logs myapp -t
heroku ps:scale web=2dokku ps:scale myapp web=2
heroku run bashdokku run myapp bash
heroku addons:createdokku plugin:install + dokku <service>:create
heroku domains:adddokku domains:add
heroku maintenance:ondokku maintenance:enable
heroku releasesdokku releases myapp
heroku rollbackdokku tags:deploy myapp <version>

The command surface is so similar that most teams create shell aliases to map their existing Heroku muscle memory to Dokku commands.

Handling Worker Processes and Schedulers

Dokku scales Procfile process types independently, just like Heroku. Your worker process type runs automatically if declared in the Procfile:

# Scale web to 2 dynos, keep worker at 1
dokku ps:scale myapp web=2 worker=1

For Heroku Scheduler replacements, install the Dokku cron plugin or use a system cron on the server to run one-off tasks. The dokku run command is equivalent to heroku run for one-off tasks:

# Run a one-off task (like a database migration)
dokku run myapp python manage.py migrate
dokku run myapp rails db:migrate
dokku run myapp node scripts/seed.js

Cost Comparison

DynosHerokuDokku (VPS)Savings
1 Basic$7/month$5/month (shared VPS)$24/year
1 Standard$25/month$10/month$180/year
2 Standard + DB$75/month$20/month$660/year
Production setup$250+/month$40/month$2,520/year

The VPS costs above assume Hetzner CX21 (2 vCPU, 4 GB, $6/month) or DigitalOcean Basic ($6-12/month). Multiple apps share a single server, so costs don't scale linearly with app count the way Heroku costs do.

Migration Timeline

DayTask
Day 1Install Dokku, create app, set up services
Day 2Migrate env vars, deploy, test
Day 3Set up SSL, domain, migrate database
Week 2Monitor, verify everything works
Week 3Switch DNS, cancel Heroku

Most teams complete a single-app migration in 1-2 days. The main time sinks are DNS propagation and database migration verification. If you're migrating multiple apps, plan one day per app.

Common Pitfalls

Buildpack version pinning: Heroku pins buildpack versions in your app settings. On Dokku, the latest buildpack version is used by default. If your app requires a specific Node.js or Python version, set it explicitly in your project files (engines in package.json, .python-version, etc.) or pin the buildpack URL to a specific tag.

File system storage: Heroku's ephemeral filesystem resets on each deploy. Dokku can persist files using Docker volumes, but you need to configure this explicitly. If your app writes files to disk (uploads, generated files), set up a Docker volume mount or switch to object storage (MinIO, Backblaze B2) before migrating.

Port binding: Dokku expects your app to bind to $PORT (an environment variable it sets), just like Heroku. If your app hardcodes a port number, change it to use process.env.PORT (Node.js), os.environ['PORT'] (Python), ENV['PORT'] (Ruby), etc.

Scaling Dokku: Multiple Apps and Workers

One of Dokku's strengths that isn't obvious from the Heroku comparison is how it handles multiple apps on a single VPS. On Heroku, each dyno is a separate billing unit — running 3 apps with 1 Standard dyno each costs $75/month. On Dokku, all three apps share a single VPS. A Hetzner CX31 with 8GB RAM at $18/month hosts 5-10 moderate-traffic Node.js or Python apps comfortably.

Each app on Dokku gets its own isolated container, its own domain, its own Let's Encrypt certificate, and its own environment variables. They share the underlying server resources, but the isolation is complete at the container level. If one app crashes, it doesn't affect the others. If you need to update one app, you push to its specific remote and only that app restarts.

Worker processes are defined in your Procfile just as in Heroku. A typical Procfile with a web server and background worker:

web: node server.js
worker: node jobs/processor.js

Dokku runs both process types as separate containers on the same VPS. Scale the web process to multiple instances with dokku ps:scale myapp web=3. Dokku's built-in proxy (nginx by default, or Caddy via plugin) load-balances across all web instances. Worker processes don't participate in load balancing — they run independently.

For background job queues, Redis is the typical choice. Install the Redis plugin once on your Dokku server, and any app can provision its own Redis instance with dokku redis:create queue-name && dokku redis:link queue-name myapp. The Redis connection string is injected automatically as an environment variable.

Monitoring Dokku Apps

Dokku doesn't include built-in application monitoring. The standard approach is to add the Grafana + Prometheus + cAdvisor stack alongside your apps. cAdvisor exposes container-level metrics (CPU, memory, network, disk) to Prometheus automatically — it discovers Dokku containers via the Docker socket. Grafana provides dashboards on top of the collected metrics.

For application-level monitoring — error rates, request latency, custom business metrics — the lightweight approach is to instrument your app with Prometheus client libraries (prom-client for Node.js, prometheus-client for Python) and expose a /metrics endpoint that Prometheus scrapes. For a complete observability setup including logs, the best open source Datadog alternatives covers the full Grafana + Prometheus + Loki stack that pairs naturally with Dokku-managed applications.

Uptime monitoring via Uptime Kuma is a natural companion for Dokku deployments. Deploy it as another Dokku app on the same server or a separate small VPS, point it at your app health endpoints, and configure notifications via Slack, Telegram, email, or PagerDuty.

Automated Deployments with Git Webhooks

Dokku's git push workflow works well for manual deployments, but production teams often want automated deployments triggered by CI/CD. The standard pattern is to push from GitHub Actions to your Dokku server via SSH. Add your Dokku server's deploy key to GitHub Actions secrets, then in your workflow:

- name: Deploy to Dokku
  run: |
    git remote add dokku dokku@your-server:myapp
    git push dokku main:main

This gives you the same push-to-deploy experience as Heroku's GitHub integration, with deployments triggered automatically on every merge to main. Combined with pre-deployment test runs in the same workflow, you get a complete CI/CD pipeline with no third-party services required beyond your VPS.

The Bottom Line

Dokku is the closest thing to Heroku you can self-host. For teams invested in Heroku's workflow, it's the lowest-friction migration path — your Procfile, buildpacks, and git push deployment all work without modification. The trade-off is that you manage the server, but for $10-40/month in VPS costs versus hundreds on Heroku, most teams find the operational overhead worthwhile.


Compare PaaS platforms on OSSAlt — deployment workflow, add-ons, and pricing side by side.

See open source alternatives to Heroku on OSSAlt.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.