A Short Heroku Survival Guide28 May 2013
The downside of services that promise to make things Magically Just Work for you are that when things go wrong – as inevitably they do – they go wrong in magical, unpredictable, and hard-to-debug ways. Heroku is no exception to this rule, as Adrian Holovaty nicely illustrates in his recent lament for the end of his personal Heroku honeymoon.
As in other areas of life, the secret to a happy and long-lasting relationship with Heroku is to start with realistic expectations and a willingness to put in some hard work. Whatever the brochures promise, Heroku doesn’t allow you to forget completely about the details of deployment. But it can, I think, offer real value over managing your own servers – especially for small organisations without full-time technical staff – and with the right preparation the pain and heartache can be kept to a minimum. Below are a few tips I’ve picked up in working with Heroku that have helped me. There’s nothing earth-shattering in here, but maybe they’ll help you too.
1. heroku run bash
This simple command is, in my experience, the biggest eye-opener for people for new to Heroku and the biggest step towards convincing them that Heroku isn’t an entirely opaque black box. It fires up a new dyno (essentially, a new server instance) with a copy of your deployed application and starts a shell session.
dave@carnap:~/projects/evans-io $ heroku run bash Running `bash` attached to terminal... up, run.9650 ~ $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=10.04 DISTRIB_CODENAME=lucid DISTRIB_DESCRIPTION="Ubuntu 10.04 LTS" ~ $ curl http://icanhazip.com 126.96.36.199
You can then interact with this shell pretty much as you would on any other UNIX box. In particular:
- You can run as many processes as you want (within the 512MB limit) and interact with them.
- You can write to the filesystem and modify existing files (although changes will only persist for the life of your session).
- You can connect to any external service you want.
- You can SSH out into other machines and use SCP to copy files back and forth.
There are a few limitations of course: you don’t have root; the Ubuntu installation you run in is pretty minimal so you might be missing your favourite debugging tool; and incoming connections are firewalled off. But generally speaking I’ve found that debugging in this way isn’t much more painful than it is on your own VPS. And it’s certainly an awful lot better than desperately deploying hundreds of tiny commits while tailing Heroku’s log output and wondering what the hell is going on (we’ve all been there)!
Incidentally, this might be one of the few situations where mastery of
(or at least minimal competence with) the venerable
ed editor might
actually come in handy for the modern developer as neither
is available in the standard Heroku environment. You won’t
want to do much serious coding with it, but if you just need to tweak
a few config values then it’s not too
hard to get the basics.
2. Get to know your buildpack
Most of the really nasty magic in Heroku is not in the runtime environment but in the buildpacks: the code responsible for taking a git checkout of your application code and producing a “slug” (a filesystem snapshot) with everything needed to run your application. Fortunately, the buildpack repositories are freely accessible on GitHub and are fairly short and easy to read.
You can read the full details of the Buildpack API
very little to it), but most of the action happens in the
compile phase. On GitHub, find the buildpack for whichever platform
you’re running on and open the
bin/compile file. You’ll find a script
(almost certainly bash) whose job is to take your source code and
produce a self-contained application, packaged up with all its
dependencies and ready to run.
It’s really worth the time to scan through this script and get a sense of what it’s up to. This is where the dirtiest hacks live (“if this version of this dependency is specified then rename this file and set this special environment variable”) and having an idea of what these are will give you a useful starting point when things start going wrong.
3. Pin your buildpack version
Having your latest deploy break mysteriously, not because of any changes you’ve made but because Heroku silently changed the buildpack out from under you, is an incredibly frustrating experience. Fortunately, it’s easy to make sure this never happens.
First, find the appropriate buildpack on GitHub and copy the read-only repository URL. For the Python buildpack, it looks like this:
Next, copy the SHA of the latest commit (there’s a handy link for this on the main repository page) and add it to the end of the git URL, preceded by a hash, like this:
Finally, tell Heroku to use this specific version of this buildpack when deploying your application:
heroku config:set \ BUILDPACK_URL='https://github.com/heroku/heroku-buildpack-python.git#23493302e665dc2428f388654a1d13fd4d437b7a'
You’ll probably want to “watch” the repository on GitHub so you get automatic notifications when it’s updated and can update the BUILDPACK_URL with the new commit SHA. It’s a little bit more effort than letting Heroku update it automatically, but not much. And now, when your latest deployment falls flat on its face, at least you know it was probably your fault.
4. Set up Heroku error alerting
Heroku errors occur at a different level from application errors and so won’t be caught by your application’s standard error handling and notification machinery. However, if your application suddenly starts being killed for hitting its memory limits you really want to know about it. It takes a minute to set up the free version of the LogEntries add-on which will send email notifications whenever one of these Heroku errors occurs. Do it now.
Any other suggestions?
Those are my four simple tips. If you’ve found them helpful, or if you’ve got suggestions of your own to add, please get in touch.comments powered by Disqus