Dokku Heroku-like self hosted platform as a service

To create app you can

dokku apps:create myApp

# to find help
dokku apps:help

# to list all apps
dokku apps:report

# similar command from docker
docker stats

# to remove destroy delete all exited docker containers
docker rm -v $(docker ps -a -q -f status=exited)


# Redis
sudo dokku plugin:install redis
dokku redis:create redis

Install swap on server, one time commands to run on server

# enable swap
cd /var
touch swap.img
chmod 600 swap.img

dd if=/dev/zero of=/var/swap.img bs=1024k count=1000
mkswap /var/swap.img
swapon /var/swap.img

echo "/var/swap.img    none    swap    sw    0    0" >> /etc/fstab


# add config environment variable: for buildpack based deployes envs are
# available during build and run time (Dockerfile based are only on run-time)
dokku config myApp
# when setting from local than you do not need to define myApp
dokku config:set RAILS_MASTER_KEY=`cat config/master.key`
# it is stored in: dokku run myApp cat  /app/.env and it is updated on next
# deploy or `ps:rebuild`


dokku ps:restart rails_6

From local machine add remote and push the code

# should point to your server, without proxy
git remote add dokku [email protected]:myApp

git push dokku master
# output should be like:
=====> Application deployed:

 * [new branch]      master -> master

Run commands from local

ssh -t [email protected] run rails_6 ruby -v
# or just using client that is downloaded in ~/.dokku
# git clone [email protected]:dokku/dokku.git ~/.dokku
# alias dokku='$HOME/.dokku/contrib/'

dokku run ruby -v
dokku run rails console

Add custom domain. On cloudlfare you can map subdomains of subdomain to dokku server, for example * so you can use any subdomain of that subdomain. Only think is that you need to add to your app

dokku domains:add myApp
dokku domains:set myApp # this will remove all other domains

dokku domains:report
dokku urls rails_6

You can inspect other nginx configuration by inspecting it and you can customize

less /etc/nginx/conf.d/dokku.conf # here we include all our apps configurations
cat /home/dokku/rails_6/nginx.conf
# upstream rails_6-5000 {
#   server;
# }
# test your application inside server
curl -I
# HTTP/1.1 200 OK

# when accessing from outside and ssl is enabled
curl -I
# HTTP/1.1 301 Moved Permanently
# Location:

Enabling https with certs letsencrypt need installation of plugin

sudo dokku plugin:install
# set global config so we do not need to set up for each app
dokku config:set --global [email protected]

than you can enable ssl for current app domains with

dokku letsencrypt myApp
# add cronjob for dokku user, check with: sudo -u dokku crontab -l
# @daily /var/lib/dokku/plugins/available/letsencrypt/cron-job
# it calls auto-renew for all certificates on dokku server
dokku letsencrypt:cron-job --add

To find all commands

dokku letsencrypt:help
dokku letsencrypt:ls

Note that wildcard certificate uses DNS-01 challenge instead of HTTP so it is not yet supported by dokku so do not use star subdomains, otherwise you will get

 File "/usr/lib/python2.7/site-packages/acme/", line 713, in poll_authorizations
    raise errors.TimeoutError()


dokku logs # when running from local machine
dokku logs myApp -t
dokku nginx:access-logs myApp -t
dokku nginx:error-logs myApp -t


Install plugin

# add postgres plugin
sudo dokku plugin:install

Create service that usually contains only one database and name is stored in cat /var/lib/dokku/services/postgres/railsdatabase/DATABASE_NAME and is the same as service so we need to create separate service for separate app (backup is for one database with the same name as service)

# list all postgres services
dokku postgres:list

# create postgres service with name railsdatabase
dokku postgres:create railsdatabase

# link with the app ie setting DATABASE_URL
dokku postgres:link railsdatabase myApp

# access postgres database
dokku postgres:connect railsdatabase

Automatic backups to amazon s3

dokku postgres:backup-auth railsdatabase $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY
dokku postgres:backup railsdatabase BUCKET_NAME

dokku postgres:backup-schedule railsdatabase $CRON_SCHEDULE $BUCKET_NAME
# for $CRON_SCHEDULE use for example `@daily`

# you can manually
dokku postgres:export railsdatabase > railsdatabase.dump

When you download dump you can extract and import in local database

tar -zxvf p.tgz
pg_restore -c -U postgres -d ruby-getting-started_development -v backup/export

or you can import this binary pg_dump to dokku

# no need to reset database, it will be automatically cleared and populated
dokku postgres:import railsdatabase < railsdatabase.dump

# if you have plain text SQL (not binary) dump you can use connect
dokku postgres:connect railsdatabase < ./plain.dump

Mount persistent storage

Herokuish Heroku will

remote: -----> Removing BUNDLED WITH version in the Gemfile.lock

Dockerfile If there are Dockerfile than it will be used except there are BUILDPACK_URL env variable or .buildpacks file. If previously buildpack was used than we need to add flag to switch to docker

dokku config:unset --no-restart myApp DOKKU_PROXY_PORT_MAP

Since env variables are using only during runtime phase, you can use docker-options plugin

dokku docker-options:add node-js-app build '--build-arg NODE_ENV=production'

so if your assets depends on some env variable, you should add it.

Dokku uses three phases:

  • build the container that executes the appropriate buildpack
  • deploy the container that executes your deployed application
  • run the container that executes any arbitrary command via dokku run

You can add triggers for after deploy actions

# app.json
  "name": "My Rails app",
  "scripts": {
    "dokku": {
      "predeploy": "bundle exec rake assets:precompile",
      "postdeploy": "bundle exec rake db:migrate"

Zero downtime deploys