This is the second post in a series. The first post is here.

In the previous post we set up a dokku server on DigitalOcean using terraform.

In this post, I’m going to show you how to host a web application on your dokku server, including setting up a PostgresQL database, and an SSL certficate using LetsEncrypt.

Pre-requisites

In addition to the tools for part one, you’re also going to need:

SSH config

Get your dokku server’s IP address like this:

$ terraform ouptut
droplet_ip = "188.166.180.22"

(Your server’s IP number will be different)

We need to tell SSH to use the key we created, whenever we connect to our dokku server, and also that we want to ssh as the dokku user. To do this, add the following to your ~/.ssh/config file:

Host dokku.me
  Hostname dokku.me
  User dokku
  IdentityFile ~/.ssh/terraform_dokku

You should now be able to ssh to your dokku server like this:

ssh dokku.me

Create an application

We’re going to create a very simple Ruby on Rails database-backed web application, "myblog", to deploy on our dokku server.

I’m going to go through the process of creating this application from scratch, and running it locally, but this is optional. In particular, if you don’t have postgres installed on your computer, you might get an error when you try to create the rails application.

You don’t actually need to get the application working locally, so if you prefer, or if you have trouble, just skip to the next section "Deploying to dokku".

Run a local database container

We need a database, so I’m going to launch a PostgresQL container with a local directory mounted into it for persistent storage:

mkdir db_files

docker run -d --rm \
    --name mypostgres \
    -e POSTGRES_PASSWORD=mysecretpassword \
    -e PGDATA=/var/lib/postgresql/data/pgdata \
    -v $(pwd)/db_files:/var/lib/postgresql/data \
    -p 5432:5432 \
    postgres

Set a DATABASE_URL environment variable to allow rails to connect to the database:

export DATABASE_URL="postgres://postgres:mysecretpassword@localhost:5432/myblog_dev"

Create the rails application

rails new myblog --skip-javascript --database=postgresql
cd myblog
rails db:setup
rails generate scaffold post title:string body:text published:boolean
rails db:migrate
git add * .gitattributes .gitignore .ruby-version
git commit -m "initial commit of myblog app."

You should now be able to run the application like this:

rails server

If you visit http://127.0.0.1:3000/posts you should be able to create and edit posts, using the default Rails scaffold web interface.

Deploying to dokku

If you didn’t create your rails application from scratch, you can get the code like this:

git clone https://github.com/digitalronin/dokku-app-myblog myblog

Before we can deploy our application, we need to do a little bit of setup on the dokku server:

$ ssh dokku.me
dokku apps:create myblog
dokku postgres:create myblog-db
dokku postgres:link myblog-db myblog

This creates a dokku app myblog with a postgres database. It also sets a DATABASE_URL environment variable in the environment where our rails application will run.

Back on our local machine, we can now deploy our rails application.

One small change we need to make is to set up a Procfile to tell dokku to run our database migrations whenever we deploy our application. Add this file to the myblog directory:

Procfile

web:     rails server
release: rails db:migrate

git add and git commit the file, then:

git remote add dokku dokku@dokku.me:myblog
git push dokku main:master

This pushes our main branch to the dokku server. It will take a while to install all the dependencies.

When it’s finished, the last few lines of output should be something like this:

=====> Application deployed:
       http://myblog.dokku.me

To dokku.me:myblog
 * [new branch]      main -> master

Since we’re using a fake domain right now, we need to add an entry to /etc/hosts in order to view our application.

echo "188.166.180.22  myblog.dokku.me" | sudo tee -a /etc/hosts

(Use the IP number for your dokku server VM)

At this point, you should be able to visit http://myblog.dokku.me/posts in your browser, and use the web interface to manage posts.

Setting a domain name

We want to use a real domain name for our application, and we also need to install an SSL certificate from LetsEncrypt, so that visitors’ traffic is encrypted, and so visitors don’t get a security warning in their browsers whenever they visit the app.

Create a DNS A record

I’m going to use the hostname dokku-myblog and the domain name digitalronin.com, so in my case, I need a DNS A record that sets 188.166.180.22 as the IP number of the dokku-myblog host.

Set up the corresponding A record with your DNS provider, using your domain name and the IP number of your dokku server.

Set the domain on dokku

Once the A record is set up, configuring the domain on the dokku server is as simple as:

$ ssh dokku.me
dokku domains:set myblog dokku-myblog.digitalronin.com

You should now be able to access the application at: http://dokku-myblog.digitalronin.com

(or rather, whatever FQDN you chose for your application)

Add an SSL certificate

Finally, let’s add a LetsEncrypt SSL certficate:

$ ssh dokku.me
dokku config:set --no-restart myblog DOKKU_LETSENCRYPT_EMAIL=[your email address]
dokku letsencrypt myblog

Now you should be able to access the application at: https://dokku-myblog.digitalronin.com, with no security warnings.

This barely scratches the surface of what dokku can do, so I’d definitely recommend having a look at the documentation.

Cleaning up

Don’t forget to use terraform destroy to shut down and delete your dokku server VM, so that you don’t incur charges on DigitalOcean.

If you’re still running your docker postgres container, you can shut it down like this:

docker stop mypostgres

Photo by Joan Gamell on Unsplash

3 thoughts on “Deploying a web application on Dokku

  1. ‘dokku letsencrypt:enable appname’ works for me but ‘dokku letsencrypt appname’ is not working. IDK why to be honest.

    I get the error: DNS problem: NXDOMAIN looking up A for “myfake.domain.com” Failed to setup letsencrypt.

    Any idea why? Am I supposed to buy a real domain ?

    Thanks for the tutorial, is really cool! Im following along with a Nodejs App 🙂

    Like

    1. Yes, you need to have a real domain name. Letsencrypt checks to see whether the domain name resolves to your server IP address, so fake domain names won’t work. The “letsencrypt:enable” step is just preparation, so that step can work with a fake domain name, but for the actual domain check and SSL certificate to be issued, you need a real domain name.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s