Paul Knittel

Noob Guide - Setup your own Heroku using Docker

May 2016

After the annoucement of Behance Prosite shutting down, which was hosting my porfolio I needed a quick and simple way to migrate my portfolio over to a new system (insert rage on startups shutting down everywhere - I’m looking at you PARSE!!). I decided to built something using the exisisting content by going through the Behance API. However to ensure that API limits would not be reached I put a node.js caching layer in between that turned out to be just about ~120 lines of code thanks to some pretty neat usage of promises.

function getProject(id) {
    return new Promise(function(resolve, reject) {
        request(apiURL + "/projects/" + id + "/?client_id=" + apiKey, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(JSON.parse(body), id);
            } else {
                reject(error);
            }
        })
    });
}

For me coding is always the fun part, but when it gets to deployment I could not imagine anything more tedious than diving into the depths of the linux directory structure to fiddle with extreme_danger.config. Heroku always appealed to me, except for their redicolous pricing that pretty much makes every website cost about $20 if you dare to have a custom domain. Luckily I found out about dokku a free, open-source, self-hosted version of Heroku. In this post I want to provide some tips that helped me setup Dokku using Digital Ocean and deploy several websites everything from node.js, php and static html files and the problems and work arounds I discovered along the way. Hopefully this article will help someone in a simillar situations as myself to save a few minutes :)

1. Server installation

Create a new droplet on digital ocean using the dokku image provided. Make sure to use your SSH keys to make deployments fast and without the need for passwords. Setup process is super simple. If you want multiple websites on one server makes sure to enable the vhost setting. My server is running only 512mb (not the recommended 1GB), however some basic stress testing (using loadimpact) shows that the performance is good enough for me.

2. Setup DNS

Pretty easy as well. Simply create an ‘A’ record for each subdomain that you’re planning to use and make it direct to your servers IP adress. For more details about setting up DNS, there are plenty of articles online.

3. Deploy app in theory

To deploy and app all you have to do in theory is define a new remote server using git and the push your code that server. Dokku figures out the rest. To add a remote in git simply go:

git remote add dokku dokku@IP-ADRESS:app-name

Not that the app name is also the name that will define what subdomain to use. So to setup my work.paulknittel.com I simply went:

git remote add dokku dokku@work.paulknittel.com:work

Then to push the code to deploy with all logs & errors shown on your terminal (what a cool git feature by the way).

git push dokku master

4. Hacks for each language

Node.js

So my node.js app was pretty easy to get running. Just make sure you have a package.json file (which you need for NPM anyway) and simply define your start script, which looked like this for me:

{
  "name": "work.paulknittel.com",
  "version": "1.0.0",
  "description": "Portfolio",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js"
  },
  ...more stuff here...
}

From there everything worked just fine.

However hosting PHP and plain HTML turned out a little more difficult.

PHP

At first Dokku was not able to detect my app as a PHP app and simply crashed when trying to identify the correct buildpack. I fixed this by forcing the heroku PHP buildpack by adding a .buildpacks file with ‘https://github.com/heroku/heroku-buildpack-php.git’ as the content. Then as specified on the buildpack php readme a composer.json file needs to be added so PHP gets detected correctly.

$ echo '{}' > composer.json
$ git add composer.json
$ git commit -m "add composer.json for PHP app detection"

From there everything worked prefectly fine for me.

Static HTML files

Unfortunately there is no way to do this out of the box. There are two main workaround soloutions:

  1. Along side dokku using nginx
  2. Or simply by using a custom buildpack

Using a NGINX configuration requires very little overhead and is great if you are low on performance or are planning to setup many website, however you loose the convenience Dokku provides of simply pushing changes to your website via git. That’s why I ended up going with the custom bulidpack option. In fact performance doens’t seem to bad. I have over 6 websites running at the same time on my server with just 512mb RAM and loading times are reasonable even under light load.

Good luck with setting up your server, I hope this article has been useful.