Avalonstar
📓

On Foreman and Procfiles

Over the last few years I’ve amateurishly covered the entire stack from design to server administration, and on that tirade I’ve managed to break many rules.

Premature optimization? Check. Refactoring without reason? Check. Overengineering? Check.

I’m obsessive-compulsive about a few things. For example, I always fold chip bags into little squares before throwing them away. But that has nothing to do with anything. I’m a very detail-oriented person, but to a fault. If I find something interesting about a particular process, for instance, I will spend exorbitant amounts of time learning its ins and outs. Wasteful? That’s a fair assumption.

But I’ll spare you the rest of the details and talk about my find of the day, the Foreman gem and the Procfile.

But don’t you program in Python?

Shut your face, that mentality is so yesterday. I will prefer the Python implementation of a program as opposed to that of its rivals if and only if it is a more elegant solution. SASS and Compass proved that to me. Anybody remember CleverCSS? Yeah, thought so. Practicality beats purity.

Alright, class is in session. Let me flip this around and show you my Procfile first, then explain what happens inside of it:

compass: compass watch static
db:      postgres -D /usr/local/var/postgres
redis:   redis-server /usr/local/etc/redis.conf
web:     python ranking/manage.py runserver

So what does it do? Instead of opening a tab in Terminal for each of those items or starting them as a daemon, it allows me to concatenate the operation into one simple command:

foreman start -f Procfile.dev

Why .dev? In my case, the sans-extension Procfile in my project is for Heroku with production-only commands. If you run foreman without the argument, it’ll look for Procfile by default. After you run that command you’ll be greeted by this lovely sight:

14:14:37 compass.1  | started with pid 3115
14:14:37 db.1       | started with pid 3116
14:14:37 redis.1    | started with pid 3117
14:14:37 web.1      | started with pid 3118

Like what you see? Great! If you’ve gotten this far, you should’ve already installed the Foreman gem by now and created a Procfile. Now, there are a few gotchas when working with your services in Foreman, especially if you’re using Homebrew, Redis and PostgreSQL:

  1. Foreman doesn’t like daemons. If you throw a command into your Procfile that dameonizes the process, Foreman will start the process only to shut down entirely because it disappeared like it was supposed to.
  2. To that point, test the commands that Homebrew gives you when you run brew info <formula> and see if it daemonizes. Here’s a freebie: the PostgreSQL command that Homebrew gives you: pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start WILL daemonize it. You’re going to want the command posted above instead.
  3. If your program logs to STDOUT it’ll all be aggregated. But if you’ve ever run redis-server through Homebrew, it’s VERBOSE. To regain your sanity, go into /usr/local/etc/redis.conf and change the loglevel to notice or warning.

On a slightly related note, I love Homebrew. I just hate the way it instructs you to start processes. It’s shit, especially if you’re coming from a Linux development environment where upstart lives to massage your feet and feed you grapes. Do yourself a favor and grab this script, throw it in your Homebrew’s bin/ and profit using brew services start <formula>, even if you don’t use Foreman in the end.

If you do a quick search on Foreman, you’ll rightfully see a slew of Ruby-centric articles. However, the amazing thing about this gem is that all it does is manage processes, so you can throw anything in there, no matter what language you happen to be programming in. Over the weekend I’ve been working on moving a wiki of ours to PHPFog, for my local install I’ve thrown php-fpm, nginx and mysql in a Procfile and it all Just Works™. No more struggling to remember commands. No more forgetting to shut processes off.

There are lots of great things that people have been doing with Procfiles, automatically running tests after saving files in Django or exporting it to upstart if you’re on Linux are just two examples.

So for once my obsessiveness has rewarded me with a streamlined development workflow, and I hope it’ll do the same for you!