Michal Zalecki
Michal Zalecki
software development, testing, JavaScript,
TypeScript, Node.js, React, and other stuff

Using Dokku with Docker, Let's Encrypt HTTPS, and redirects

This post is a step by step guide to configure Dokku to host multiple applications, supporting domains, subdomains, redirects, and secure connection via HTTPS using free certificates issued by Let's Encrypt.

After completing this tutorial, you set up the server that can serve multiple dockerized application for as low as $5 a month. I'm using a very similar setup to run this blog and my side projects.

Dokku is a self-hosted platform as a service that tries to mimic the way Heroku works and uses Docker to isolate, manage, and run multiple applications. It's designed to run on a fresh VM installation and abstracts configuring nginx to using a few simple Dokku commands. You can deploy your application by pushing to the git repository that Dokku maintains for each of your applications, just like Heroku does.

Make sure you follow the steps in the right order.

Setup Dokku

Thanks to one-click Dokku droplet installation, DigitalOcean is the easiest way I know of to get started with Dokku. Use this referral link to get $10 in credit for signing up on DigitalOcean. You can use your credits to follow this guide and run Dokku on the cheapest instance for two months.

You can also install Dokku yourself. Dokku provides you with a shell script that will take 5-10 minutes to complete. Head to Dokku documentation for the information on the latest version.

wget https://raw.githubusercontent.com/dokku/dokku/<VERSION>/bootstrap.sh;
sudo DOKKU_TAG=<VERSION> bash bootstrap.sh

Once you have a Dokku installed go to your server IP address using your browser.

open http://<SERVER_IP>

Dokku serves the web installer on the default port 80. Paste your public key and remember to select the use virtualhost naming checkbox.

Execute the following command on your local machine to find out what's your public key.

cat ~/.ssh/id_rsa.pub

Create and deploy the application

SSH into your server

ssh root@<SERVER_IP>

Create a new application

dokku apps:create <APP_NAME>

Optionally, you can configure the environment variables before the first deployment.

dokku config:set <APP_NAME> KEY1=VALUE1 KEY2=VALUE2

Switch back to your local machine, enter your git repository and add a dokku remote.

git remote add dokku dokku@<SERVER_IP>:<APP_NAME>

You can now push to dokku repository to deploy the application.

git push dokku master

Dokku derives some configuration from your Dockerfile like ports mapping based on the EXPOSED instruction.

Domain configuration

Dokku can support multi-domain configuration. Go to your DNS configuration and point your domain using A record to the server IP address.

IN A <SERVER_IP>

Optionally you can set a CNAME record for the www (or different) subdomain.

www IN CNAME <DOMAIN_NAME>.

Create a CNAME record with the destination address set to server IP address if the higher-level domain doesn't point to the server IP.

staging IN CNAME <SERVER_IP>

Now, you have to tell Dokku what domain the application should handle.

dokku domains:add <APP_NAME> <DOMAIN_NAME>
dokku domains:add <APP_NAME> www.<DOMAIN_NAME>

You can check which application handles what domains.

dokku domains:report

Remove any unnecessary domain configuration that is a leftover after the app creation.

dokku domains:remove <APP_NAME> <APP_NAME>.dokku-s-1vcpu-1gb-fra1-01

If you decided to configure www subdomain, your application is accessible under both www.<DOMAINNAME> and <DOMAINNAME>. It would be better to settle on one and set up a 301 redirect. We will wait with setting up redirects till we have a valid SSL certificate for both domains.

TLS/SSL certificates

I'm going to use Let's Encrypt CA to obtain free TLS certificates. Dokku doesn't support Let's Encrypt by default, but there's a plugin for that we can install.

sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

It's important to expose the application to the host on the port 80.

dokku proxy:ports-add <APP_NAME> http:80:<CONTAINER_PORT>

Let's Encrypt requires you to specify an email address. You will receive notifications before the certificates expire.

dokku config:set --no-restart <APP_NAME> DOKKU_LETSENCRYPT_EMAIL=<EMAIL>

Request certificates and complete the ACME protocol challenge automatically.

dokku letsencrypt <APP_NAME>

In case of any problems with domains make sure the DNS records propagated correctly. It might be the reason why Let's Encrypt challenge is failing.

Check the ports configuration for your application. If you successfully obtain the certificates, you can see that host's port 443 is mapped to the same port as the port 80.

dokku proxy:ports <APP_NAME>

You can also remove automatically mapped ports if you don't need them any more.

dokku proxy:ports-remove <APP_NAME> http:<HOST_PORT>:<CONTAINER_PORT>

Redirects

Although Dokku does not support redirects out of the box, there's another plugin to remedy that.

dokku plugin:install https://github.com/dokku/dokku-redirect.git

Now you can configure 301 redirect from www.<DOMAINNAME> to <DOMAINNAME>.

dokku redirect:set <APP_NAME> www.<DOMAIN_NAME> <DOMAIN_NAME>

Conclusion

Until you start to modify nginx files not knowing what are you doing, Dokku is a reliable platform to host your applications. Dokku combines the ease of use of Heroku with affordable pricing of VPS providers like DigitalOcean or Linode.

It's still possible to run Dokku behind the custom reverse proxy by excluding dokku-generated files from the nginx configuration. Despite missing out on a few features, going with Dokku is still a good choice if your goal is supporting git-based deployments and having a way to expose the app on the selected port.

If you find this article helpful use this referral link to get $10 in credit for signing up on DigitalOcean.

Photo by Erwan Hesry on Unsplash.