Skip to content

Migrate from Dokku

Dokku is a single-host “mini-Heroku” — great until you need more than one host. dockmesh is the natural next step if your reason for moving is scale, not PaaS features.

  • You’ve outgrown a single Dokku host and need multi-host
  • You want git-push deploys + multi-host management
  • You need RBAC/SSO (Dokku Pro is paid)
  • You want backups managed by the orchestrator
  • You love git-push deploys and don’t need multi-host → stay on Dokku
  • Your apps use Dokku’s buildpacks (Heroku buildpacks) and you don’t want to Dockerize → stay on Dokku

dockmesh is not a buildpack-based PaaS. You need Dockerfiles.

If your Dokku apps are Docker-based already (dokku builder-dockerfile:set), skip this step.

If they use Herokuish/buildpacks, convert:

# Example for a Node.js app
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app ./
EXPOSE 3000
CMD ["node", "server.js"]

Test locally:

Terminal window
docker build -t myapp .
docker run -p 3000:3000 myapp

Do this for each app. The compose.yaml comes next.

On a new host (or your existing Dokku host — they coexist):

Terminal window
curl -fsSL https://get.dockmesh.dev | bash

Step 3 — Convert Dokku apps to Compose stacks

Section titled “Step 3 — Convert Dokku apps to Compose stacks”

Each Dokku app becomes a dockmesh stack. A simple one:

services:
app:
image: ghcr.io/yourorg/myapp:latest
restart: unless-stopped
environment:
DATABASE_URL: ${DATABASE_URL}
NODE_ENV: production
depends_on: [db]
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:

For Dokku apps with attached databases (dokku postgres:link), add the DB as a service in the same compose file (as above).

Terminal window
# On Dokku host
dokku postgres:export myapp-db > myapp-db.sql
# Copy to dockmesh host
scp myapp-db.sql dockmesh-host:/tmp/
# Restore
docker exec -i myapp_db_1 psql -U postgres < /tmp/myapp-db.sql

Dokku’s /storage mount becomes a named volume:

Terminal window
# On Dokku host
tar czf myapp-storage.tar.gz -C /var/lib/dokku/data/storage/myapp .
# On dockmesh host
docker volume create myapp_storage
docker run --rm -v myapp_storage:/data -v /tmp/myapp-storage.tar.gz:/src.tar.gz alpine \
tar xzf /src.tar.gz -C /data

Then in compose:

services:
app:
volumes:
- myapp_storage:/app/storage
volumes:
myapp_storage:
external: true

Dokku uses nginx + Let’s Encrypt. dockmesh uses Caddy.

For each app in dockmesh:

  1. Stack detail → Proxy → Add route
  2. Domain: same as Dokku (e.g. myapp.example.com)
  3. Target: the app’s container
  4. TLS: Automatic

DNS doesn’t need to change if the dockmesh host IP is the same. If different, update DNS before cutting over.

Dokku’s killer feature is git push dokku main. Replicate it with:

Configure the stack as Git-backed: dockmesh polls a Git repo for compose.yaml changes + image tag updates.

Use GitHub Actions or GitLab CI to:

  1. Build on push
  2. Push image to registry
  3. Call dockmesh API to redeploy

Result: git push still triggers a production deploy. More machinery, more flexible.

Once all apps migrated and traffic cutover via DNS:

Terminal window
# On the old Dokku host, remove Dokku itself (if dedicated machine)
apt remove dokku
rm -rf /var/lib/dokku

Keep the host around for a week as rollback. Delete once confident.

  • Buildpacks — you need Dockerfiles
  • dokku logs --tail from CLI — use UI or docker logs via SSH
  • dokku config:set — use dockmesh UI env vars (arguably better)
  • dokku ps:scale web=3 — dockmesh has Scaling with similar semantics
  • Plugin ecosystem — dockmesh has fewer plugins (it’s a different architecture)
  • Multi-host
  • RBAC + SSO
  • Audit log
  • Backup target types beyond local
  • Prometheus metrics
  • Web UI (Dokku has the commercial Dokku Pro for this)