Foreman - a process manager for your web applications

  • Tutorial
A web application development model based on the idea of ​​scaling with processes is becoming increasingly popular. A modern application is a set of running processes that do not store state, and each is isolated from each other. Each such process is assigned its own local port, which allows you to transparently export your services for subsequent consumption by someone else, perhaps even each other (for example, one serves http requests from users, accepting video urls, and the other slowly but true, download them and convert). As a rule, in most cases, http-services are simply set for reverse proxy in nginx, but options are possible.

It's no secret that each developer has his own arsenal of tools that allows him to make his life easier anyway. Today we’ll talk about a tool like Foreman. Using it, you can declare in one place all the processes that are necessary to run your application. To do this, use the so-called Procfile, which looks something like this:

web:    mono ./awesome-app --port $PORT
api:    node ./api.js -p $PORT
worker: bundle exec rake resque:work QUEUE=*
habr:   bundle exec ./bin/thin -a localhost -p $PORT

As you can see, everything is quite simple, each line of the file contains the name of the process type and a line to start it.

▌ Installation and use


To start using it, just install it using your system package manager or using rubygems:

$ gem install foreman

If your application uses Foreman, then its launch, if there is a ready-made Procfile, will look quite simple:

$ editor .env
$ foreman start

Here's what the launch of all processes looks like:



Foreman sets the necessary environment variables, starts all the processes associated with your application, and also displays the output of the standard threads (stdout and stderr) of each. As you can see, the names of the processes are painted in different colors, which allows you to visually distinguish them. The value of the variable is $PORTautomatically set by Foreman separately for each started process.

It should be noted that your processes should not be demonized themselves, because Foreman will not be able to control the cycle of their start-stop in this case.

▌ Deployment


Foreman can export your startup tasks to upstart , as well as to the classic Unix init (however, this is not recommended), bluepill , runit and supervisord . Systemd support is also on the way .

Export to upstart


$ foreman export upstart /etc/init
[foreman export] writing: /etc/init/testapp.conf
[foreman export] writing: /etc/init/testapp-web.conf
[foreman export] writing: /etc/init/testapp-web-1.conf
[foreman export] writing: /etc/init/testapp-worker.conf
[foreman export] writing: /etc/init/testapp-worker-1.conf
[foreman export] writing: /etc/init/testapp-habr.conf
[foreman export] writing: /etc/init/testapp-habr-1.conf

After exporting to upstart, the following commands become available:

$ start testapp
$ stop testapp-habr
$ restart testapp-worker-1

Export to inittab


$ foreman export inittab
# ----- foreman testapp processes -----
TE01:4:respawn:/bin/su - testapp -c 'PORT=5000 mono ./awesome-app --port $PORT >> /var/log/testapp/web-1.log 2>&1'
TE02:4:respawn:/bin/su - testapp -c 'PORT=5100 bundle exec rake resque:work QUEUE=* >> /var/log/testapp/worker-1.log 2>&1'
TE03:4:respawn:/bin/su - testapp -c 'PORT=5200 bundle exec ./bin/thin -a localhost -p $PORT >> /var/log/testapp/habr-1.log 2>&1'
# ----- end foreman testapp processes -----


▌ Features


Parallelism



Foreman allows you to control the number of running instances of each type of process, which also echoes the idea of ​​scaling using processes. By the way, this approach has already been liked by Heroku users .

# запустить по одному экземпляру процесса «worker», четыре процесса «habr» и два «web»
$ foreman start -c habr=4 -c web=2

# то же самое, только не запускать, а экспортировать в upstart
$ foreman export upstart /etc/init -c habr=4 -c web=2

# не запускать процесс «worker»
$ foreman start -c worker=0

Environment variables


There is an approach that is gradually gaining popularity among developers, which consists in storing the application configuration in environment variables. Foreman here did not stand aside and allows to simplify everything.

In order to use this feature, in the project directory it is necessary to create a file .envcontaining an enumeration of all the necessary values ​​of the environment variables, for example:

APP_ENV=production
DATABASE_URL=mysql://user:password@localhost/table

It’s good practice to create and register a file version control system with sample.envan example configuration of your application. Thus, to deploy it in a new environment, you will need to copy the file sample.envto .env, edit it according to your environment, and then run Foreman.

You can also ask Foreman to start processes with environment variables from another file:

$ foreman start -e development.env

Port Assignment


By default, Foreman assigns ports to processes starting at 5000, and does this in blocks of 100 for each type of process, in the order in which they are listed in Procfile.

Say, for the Procfile from the example above, the web.1 process will receive the 5000th port, worker.1 the 5100th, and habr.1 the 5200th. If you start two habr processes, then the port number 5201 will be assigned to the habr.2 process.

You can also select the start port manually, for example:

$ foreman start -p 7000


▌ Conclusion


As you can see, there’s absolutely nothing complicated in using such good practices, and this time saves enough time to be in the arsenal of an advanced developer.

For more information about all the available features, you can refer to the documentation , as well as the project repository page on github.

Also popular now: