Dokku is a lightweight PaaS solution that let's you essentially have a mini self-hosted Heroku. This means you can easily take a web application (Django, Rails, etc.) and deploy it with little to no setup. While Heroku offers scalability and support, it does so at a significant cost ($) beyond a very low volume; if you're planning to deploy lots of small or in-development apps, then you don't necessarily need everything Heroku offers, you just need an easy way to (git) push your apps out there.
I'm going to walk through the setup of Dokku and then demonstrate how to deploy a Django app with a PostgreSQL database (however, the instructions can be easily re-applied to other frameworks, like Rails).
Initial Dokku Setup
We can host Dokku on almost any VM or Dedicated Hosting provider (or even your own machine). I went with DigitalOcean which offers a small instance for only $5/month (and can easily be grown as needed); other great options are Linode (which I also use), and EC2.
Not doing any advance reading about it's requirements, I first tried to set it up on an existing 32bit VM, and then again an Ubuntu 12.10 64bit VM. Unfortunately, I came to the late realization that Docker, the lxc-based container solution that Dokku is built atop, is only compatible with 64bit Linux, and only runs stable on kernel versions greater than 3.8 (Ubuntu 12.10 comes with 3.2, 12.04 is easily upgradable to 3.8). [4/2014 Note: there are currently issues with Docker and Ubuntu 13.10] Eventually, I went with the Dokku's preferred target OS of Ubuntu 13.04 x64. After this point, setup was trivial:
wget -qO- https://raw.github.com/progrium/dokku/v0.2.2/bootstrap.sh | sudo DOKKU_TAG=v0.2.2 bash
After the bootstrapping has run, you'll want to register your SSH public key with Dokku (USERNAME in this case is an arbitrary identifier for your key) so you're able to push your apps up; from your machine:
cat ~/.ssh/id_rsa.pub | ssh yourserver.com "sudo sshcommand acl-add dokku USERNAME"
It's also simplest to have a domain dedicated to your Dokku instance, with a wildcard subdomain DNS entry so that any apps you deploy instantly have an easily accessible address. On many DNS management tools (including that of DigitalOcean and Linode) you can setup a CNAME or A record that points *.yourdomain.com to your new instance.
Once you have setup your DNS records, verify that
/home/git/VHOST on your server is set to the base of your domain (i.e. yourdomain.com).
Note: It is also possible to use a sub-sub-domain (i.e. *.dev.yourdomain.com), but many DNS management tools don't easily support this.
Note 2: You can also forgo using a domain entirely, in which case Dokku will provide you with IP/port combinations for each of your deployed apps.
Setting up a database
We're almost ready to deploy our first app, but we'll probably need some sort of database also. If your app(s) don't require one, you can skip this step.
Dokku supports plugins for various database engines including PostgreSQL, MariaDB (i.e MySQL), and MongoDB. For the purposes of this example, we're going to setup PostgreSQL (although similar instructions apply for others).
To install the PostgreSQL plugin, on the server:
cd /var/lib/dokku/plugins git clone https://github.com/Kloadut/dokku-pg-plugin dokku plugins-install
Now our instance is ready to host PostgreSQL databases; we'll hold off on actually creating one until we setup our first application:
Deploying your first app
Dokku aims to be compatible with Heroku's buildpacks; buildpacks provide the infrastructure to setup a container for running various apps built on various languages and frameworks. Currently, Dokku supports:
- and more
For the purposes of this example, we're going to assume that we're trying to deploy a Django/Python web-app. However, we're going to ground this mini-tutorial in the one's provided by Heroku (because Dokku's model is so similar), so you'll be able to follow along with nearly any of their "Getting Started" tutorials and make parallel changes for other types of apps.
To setup our new Django project, you can follow the Heroku tutorial exactly until the "Deploy to Heroku" step; this is the first point where there is some minor divergence in process.
Unlike Heroku, there is no explicit app creation step; we will just push to a new git remote that names our app and will serve as our deplyment destination. Let's assume that we want to be able to access our new app from testapp.yourdomain.com:
git remote add dokku [email protected]:testapp git push dokku master
At this point, Dokku will begin creating your new app: setting up a new docker container, installing the build pack, and detecting our new application. When it is finished, we will simply be able to visit
http://testapp.yourdomain.com, and we should be greeted by our new application -- however, at this point, our database is still not ready for our app.
dokku commands need to be run on the server because dokku has no official client-side app like heroku; for added convenience, you may create a client-side alias that allows you to use the dokku command 'locally':
alias dokku="ssh -t [email protected] dokku"
To create a PostgreSQL database corresponding to our application and have the database URL automatically associated with the application:
dokku postgresql:create testapp dokku postgresql:link testapp testapp
The plugin will detect our pre-existing application, and automatically include the new database's connection information in the application's ENV (which in Django's case, the dj-database-url package will pick up).
Now we want to populate our tables into the database. For Django, this means running
manage.py syncdb; however, this needs to be run from within our container. Similiar to Heroku's
heroku run, we can execute:
dokku run testapp python manage.py syncdb
However, because this command runs non-interactively (unlike Heroku), we will lose our opportunity to create a Django super-user. Currently, dokku provides no easy way to get access to an interative shell within a container (although I have submitted a patch to add support for this). Until official support is added, one solution for this is borrowed from dotCloud: We can commit a script
createadmin.py that will create our initial super-user:
Edit (10/9/13): My patch was merged in that allows for interactive commands to run via dokku, so there should no longer be an issue running manage.py syncdb via dokku.
After we push this to our dokku instance, we can simply run:
dokku run testapp python createadmin.py
Our Django app is finally up-and-running with a populated database, and we should be able to access it and login to the /admin interface.
Now that we have a Dokku instance and understand how to leverage it, deploying new apps is made relatively trivial. Although lacking in horizontal scalability, we now have our own affordable "mini-Heroku" that allows us to build and deploy "unlimited" applications. It serves as an ideal environment for staging, prototyping, and deploying non-critical apps.