Dokku

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the containerization category.

Last Updated: 2024-04-25

Dokku is similar to Heroku (using Docker), except in runs on your own metal. Use it to deploy Heroku buildpacks or to deploy Dockerfiles

At time of writing, it is fussy about OS (Ubuntu fine, Amazon linux not supported)

Install on linux

Create a machine with web and SSH access on AWS then SSH in using the key you provided AWS when creating your server

ssh ubuntu@3.126.51.166

Install on ubuntu (update the version no. to latest, of course)

wget https://raw.githubusercontent.com/dokku/dokku/v0.24.5/bootstrap.sh;
sudo DOKKU_TAG=v0.24.5 bash bootstrap.sh

Check if it ran successfully (look at errors from read out)

Visit your server's IP address in a browser and you'll see an admin area with your public key as confirmation.

On the server, create a dokku app

dokku apps:create my-app-custom-name

Back on your development machine

Then to deploy

# NB: This assumes local is `master` and Dokku is configured to master on the server
# as its default branch.
git push dokku master

Docker Deploys

For security reasons - and as per Docker recommendations - Dockerfile-based deploys have variables available only during runtime. This is different to config:set used in Heroku and the buildpack flow of dokku that makes them available earlier.

Built time variables are set as follows:

dokku docker-options:add my-app-custom-name build '--build-arg NODE_ENV=production'

And consumed as follows

Once set, the Dockerfile usage would be as follows:

FROM ubuntu:18.04

# set the argument default
ARG NODE_ENV=production

# assign it to an environment variable
# we can wrap the variable in brackets
ENV NODE_ENV ${NODE_ENV}

# use the argument
RUN echo $NODE_ENV

To specifize dockerfile location:

dokku docker-options:add my-app-custom-name build '--file Dockerfile.dokku'

Ensure the internal Docker ports (see Dockerfile) connect to ports of the host that are open (via firewall and/or AWS Security Group)

dokku proxy:ports my-app-custom-name

# Map port 80 of the host to 8000 of the dockerfile.
dokku proxy:ports-set my-app-custom-name http:80:8000

Set secrets and config (many at once)

# This works in docker deploys too, and the variables are available
# in running containers as part of the ENV
dokku config:set my-app-custom-name APPLICATION_ID="abc" PASSWORD="asdf"

# To remove a key, use `config:unset`

Ensure any needed data bindings are done correctly by added flags via docker-options subcommands of deploy,run,build or some comb

dokku docker-options:add my-custom-app-name deploy "-v /var/log/node-js-app:/app/logs"
dokku docker-options:add my-custom-app-name run "--mount type=bind,source="$(pwd)"/abbyy,target=/app/abbyy"
# You might need to restart here

Now curl localhost:80 in production and see what happens.

How to convert various Docker instructions into Dokku instructions

sudo docker build -f Dockerfile . -t nka:preliminary`

Troubleshooting

If you interrupt a deploy (e.g sending a signal), you need to unlock server-side

dokku apps:unlock my-app-custom-name

Double check your ports are correct

Small mistakes lead to total failure

To get in depth reports, ask Dokku

dokku report my-app-custom-name

How to restart app

dokku ps:restart my-app-custom-name

Git freezes

ssh -vvvv dokku@111.11.42.119

Go inside a container

dokku enter my-app-custom-name
env # e.g. check if ENV variables arrived to container correctly

Enable trace logs and view logs

# Tailing logs
dokku logs my-app-custom-name -t

See processes status

dokku ps:report my-app-custom-name
=====> my-app-custom-name ps information
       Deployed:                      true
       Processes:                     1
       Ps can scale:                  true
       Ps restart policy:             on-failure:10
       Restore:                       true
       Running:                       true
       Status web 1:                  running (CID: 5c5a1fbc286)

Pro-tips:

  1. Run all these commands from your dev machine (it "just works"). What's more, the app name need not be specified - e.g. dokku enter myappname becomes docker enter

Great resources