Slack bot experimentation, especially for not-too-serious purposes, has become a little too expensive on Heroku. There’s no free tier for maintaining apps running 24/7, so the dollars add up quickly at 7x12=84$ a year per application. I am currently running playplay.io, shell, api-explorer and market. Add another $18x12 = $216 for a non-free-tier MongoDB for one of the apps and it’s no longer a coffee-money bill.
I’ve always liked and thought highly of DigitalOcean, but loved the convenience of Heroku and enjoyed having all my apps in one place with a consistent git workflow. Yesterday one of DigitalOcean developers kindly offered me some droplet credits to run one of the bots their team uses. I decided that free beats convenient and that it’s time to do some work, save money and learn a few things.
tl;dr A 20$ droplet can easily run half a dozen Ruby bots. I won’t miss Heroku much.
Getting a Droplet with Dokku
Sign up for a DigitalOcean account. If you haven’t, use my referral link, and thank you. Enable two-factor auth and create a Dokku droplet from within One-click Apps. I use a 20$ one, but smaller works too.
Dokku is a docker-powered PaaS. These days it’s very mature and works flawlessly.
You’ll be asked for an SSH key during setup. Use your existing one or generate a new one with ssh-keygen
(I made digitalocean_id_rsa
and digitalocean_id_rsa.pub
), copy-paste the contents of the .pub
file into the box during signup and save the private and public keys in a vault (I use 1Password).
DigitalOcean boots a droplet and assigns it an IP address. I use DNSimple to give it a name via an A DNS record as well as a wildcard entry.
Finally, navigating to the droplet’s URL and clicking a couple of buttons will complete the Dokku setup.
SSH and Dokku
Install dokku-cli
via gem install dokku-cli
. Adding a dokku
remote to your local git repository will let you run dokku config
and other commands just like on Heroku. You can also SSH to the Droplet and run commands from there. It’s just a Linux Ubuntu box.
You can run dokku
to get all the available commands.
MongoDB
My bot stores data in MongoDB, so I need to get that into Dokku.
Create a database. This actually starts a MongoDB instance which is not accessible from the outside world.
Of course you don’t have to do any of this and signup for a MongoDB hosting provider like MongoLab or Compose, too.
See also Installing and Upgrading MongoDB in Dokku.
Creating an App
Creating an app is very similar to Heroku. In fact, this uses herokuish, a utility for emulating Heroku build and runtime tasks in containers, so from now on everything pretty much looks like Heroku.
We want to link the MongoDB container to this app, ie. publish a MONGO_URL
configuration setting to the app and connect the apps logically.
Any other environment variable can be set as well.
Supervisord
Install dokku-logging-supervisord to auto-restart crashing processes, just like on Heroku. Use this fork to avoid docker-locking-supervisord#34 which points to docker#18543 as a bug that causes hangs on restart.
This will also cause application log files to go into /var/log/dokku/[app name]
, so you can tail -f
those normally.
Pushing Code
Dokku supports Git workflow. Add a remote and push code to it.
The app is now available at market-bot.dblock-plum.digitalocean.playplay.io, much like any herokuapp.com applications. I added a DNS CNAME market.playplay.io entry pointing here and told Dokku about it.
Hot Deploys
When a new version of a bot is deployed, Dokku will wait DOKKU_WAIT_TO_RETIRE
to shutdown the previous instance. You may not want two instances of a bot to hang around and either set this time to zero or a smaller number.
New Relic
Sign up for New Relic and configure it for Docker as described here, which gives you a view inside the Docker containers.
Lets Encrypt
Setup SSL as described here.
For a new app.
Things I Will Miss
The only thing I will miss from Heroku is the ability to change the number and the size of each process. Other than that the DigitalOcean + Dokku combination is much more cost-effective and equally convenient.