Process configuration management with Foreman
Often in the Rails projects I build, I have a need to store configuration that I don’t really want to have in my code. The most obvious way to do this is to either store the configuration in a YAML file (e.g.
config/settings.yml), or in environment variables.
If you’ve ever worked with Heroku, you’ve probably seen the
heroku config command. When you run this command on an active Heroku project, you see output like this:
This configuration is actually managed by Foreman, and is stored in a file called ‘.env’ in the root of the project. The .env file for the configuration above would look like this:
The cool thing about Foreman is that you can use this .env file just as easily locally. All it does is reads the file when you run a command, and loads these variables into your shell as environment variables.
The other functionality that Foreman provides is the ability to run and manage multiple processes. This is something that you may or may not have run into in Heroku, but it’s still pretty cool. Without Foreman, if you had a Rails server, a PubSub server (Faye, for example), and a daemon to run, you might have to do the following:
- New terminal tab, run
bundle exec rails s
- New terminal tab, run
bundle exec rackup faye.ru
- New terminal tab, run
bundle exec script/daemon start
…and then you need to keep an eye on each of these tabs.
With Foreman, you create a file called a
Procfile. This stands for ‘Process file’, and is a simple listing of the processes you would like to run. For example, on-the-spot’s
Procfile looks like this:
When you run
foreman start, Foreman will boot up each of these processes, and output the combined logs for all in the window. When you stop Foreman (By hitting Ctrl-C), it will shutdown each of the processes before exiting. This process is much easier to handle than multiple terminal tabs.
There’s two ways to install Foreman:
- Via the Heroku Toolbelt. Heroku publishes a ‘Toolbelt’ - a collection of tools required to develop applications that run on the Heroku platform. I don’t use this method myself, as I prefer to have control over what’s installed and where, but you can install this from
https://toolbelt.heroku.com/if you’d like
- As a gem. You can just run
gem install foremanto get it installed - easy as that. If you’re using RVM, then you may want to follow my pattern - I normally place Foreman in my global gemset along with the
herokugem, so that it accessible to all my apps. If you’re just experimenting with Foreman though, you may want to place it in it’s own gemset.
Foreman is actually pretty easy to use on a day-to-day basis - there’s really only two commands you need to run:
foreman run [cmd]- You can run any command with Foreman, doing all the environment variable setup, etc. beforehand. If you require any variables in your application’s setup routine, then you will need to run all your
rake *commands with this, otherwise you can just run it when you need access to these variables.
foreman start- Use this command to start all the processes listed in your
Procfile, and just
Ctrl-Cwhen you want to stop them.
Easy as that really. There’s a bunch of other things you can do with Foreman (such as exporting launchd and init.d scripts to run your application automatically), but they’re not really something you’ll need to know to get started.
Debugging Ruby with Foreman
A common complaint I hear about Foreman is that it’s quite complex to debug application’s in. This is a consequence of the way that Foreman combines the running of all of the processes in your Procfile into a single output flow - debugger’s can’t easily make it through. I’ve found there’s a couple of ways to debug with Foreman though:
- Run a Rails debugging server with
foreman run. Since
foreman rundoesn’t do any of the fancy
Procfilestuff, you can just run
foreman run rails s --debuggerwhen you do need to debug - it will behave just as it always has.
- Use a debugging console directly in Foreman. I’ve had mixed results with this, but if you do run with
Foreman startand have debuggers in your code, I have noticed that these breakpoints do get hit - it’s just that Foreman doesn’t always output the prompt characters for the debugger. You can still type in
irbto drop into an IRB session, and everything will behave as it usually does from here - it just requires a keen eye to spot when you’ve landed on a debugger in Foreman (since there won’t be any output)
- Run a remote instance of ruby-debug and connect that way. Ruby’s debugging support includes the ability to run a debugging server from your application, that you can connect to from another terminal window or tab. To do this, you need to do a bit of setup in an initializer, but once it’s there, it’s pretty seamless:
config/environments/development.rb, add the following lines:
- In a new terminal window or tab, run the
rdebugprogram to connect to your remote debugging instance:
- (More info on this Github issue)
I do prefer the first two options to the last, as I find that code changes seem unnecessary for this, and I normally aren’t needing to debug all the time. Largely though, this is up to personal preference, and I wanted to present all options.
Foreman is a pretty awesome tool for development, especially for those apps that may have some complex configuration and process management needs. I don’t use it for all my applications (since I’m a strong believer in picking just enough of the right tools for the job), but I do find it incredibly handy to extract all my configuration and processes into external files that I can easily update and generally DRY up my code.
Information: This blog post is based on a lightning talk I delivered at 3months for the dev team. 3months is an agile-based company based in Wellington, New Zealand. We have fun. Interested in working for us? Give us a shout!