Procfile
Procfile support is one of our compatibility layers that makes Scalingo compatible with Heroku.
About the Procfile
The Procfile is a simple text file specifying how the platform should start your application’s container(s).
More precisely, it allows to declare the commands executed in the container(s) on startup.
Each of these commands is associated to a process type, which is basically a name that uniquely identifies the type of process.
When the platform starts a container for your application, it uses the process type to know what command to execute in it, and it also marks the freshly booted container as being of the specified process type, thereby creating a kind of link between the container and its process type.
Consequently:
- a container belongs to exactly one process type.
- a process type can reference zero, one or multiple containers, depending on the scale factor.
Since process types are referencing containers, they are also used to manage the resources consumed by your application:
- they allow to add or remove container(s) of the specified process type.
- they allow to set different plans for the containers, depending on the workload they have to handle.
You can define as many process types as you need for your application, from the same code base.
Some common use cases for process types:
- define a process type called
web
to start a process handling HTTP requests. - define a process type called
worker
to handle some asynchronous computation. - define a
clock
process type to schedule some recurring jobs. - …
Example:
Let’s say your application has a web frontend that handles HTTP requests and a worker that does some heavy computing. They both share the same code base, but they don’t start the same way and they don’t have the same computing power requirements. In such a case, you’d have to instruct the platform to start two process types, which must be defined in your project’s Procfile:
- one called
web
, to instruct the platform how to start your web server (the frontend). - another one, called
worker
, to instruct the platform how to start your… worker.
The web
process type could be set to use an L
plan (which means the
platform will run the corresponding command in an L
container), whereas
the worker
process type could be set to use a 2XL
plan.
Now, let’s say that your single worker
container is a bit under pressure.
Using the process type, you can instruct the platform to boot up a few more
containers to handle the load (in the command below, we tell the platform that
we want three 2XL
containers for the worker
process type):
scalingo --app my-app scale worker:3:2XL
Special Process Types
The web
, tcp
and postdeploy
process types have a special meaning and are
thus reserved for specific use cases described below. The platform will only
use them for what they are designed for.
The web
Process Type
The web
process type defines how to start and run the container(s) handling
HTTP requests.
It’s the only process type that can receive external HTTP requests from
Scalingo’s routers.
Consequently, if your application has a web server, it MUST have a web
process type bound to $PORT
to be publicly reachable.
The web
process type is often the only one required.
The tcp
Process Type
The tcp
process type defines how to start the
TCP Gateway addon.
The postdeploy
Process Type
The postdeploy
process type defines how to start the
postdeploy hook.
Working With the Procfile
Procfile Naming Convention
The Procfile is a plain text file that MUST be named Procfile
. Even if it
uses the YAML syntax, there is no extension: no .txt
, no .yaml
, no
.yml
. Only Procfile
.
The file MUST live in your application’s root directory or in $PROJECT_DIR
,
if your application code lies in a subdirectory of your repository.
Defining a Process Type
Each process type of the application is defined on its own, individual line, with the following format:
<process_type>: <command>
-
<process_type>
designates the name of the process type. It can only contain alphanumerics ([A-Za-z0-9]+
). Except this rule, you are free to name your process type how you want:heavyProcess
,synchronizer
,scheduler
,console
,trex
… These are all examples of valid process type names. -
<command>
designates the command to run when a container of the specified type is booted up. It can be any Bash command. Using environment variables in the command is allowed, and even encouraged.
Here is an example of a valid Procfile defining two process types:
- one called
web
, defining how to start a Rails web server. - another one called
worker
, defining how to start a container running Sidekiq.
Notice the use of the environment variables:
web: bundle exec rails server -p $PORT -e $RAILS_ENV -b 0.0.0.0
worker: bundle exec sidekiq -e $RAILS_ENV
Defining a Complex Process Type
When you have more complex commands to run, don’t hesitate to write a short
start script, for instance in bin/start.sh
:
#!/bin/bash
if [ "$SOME_ENV" = "SOME_VALUE" ] ; then
exec run_this_command -p $PORT
else
exec run_that_other_command
fi
Then, in your Procfile
, call this script directly:
web: bash bin/start.sh
Starting and Stopping a Process Type
When starting or stopping a process type, you concretly instruct the platform to create (and start) or stop (and destroy) all the container(s) referenced by this process type. In fact, these operations are the same and consist in scaling the process type, which can be done via the dashbord or via the CLI.
All new process types are considered to be scaled to 0:M by default and,
hence, must be scaled to a value greater than 0 to be started by the platform.
The only exception is the web
process type, which is scaled to 1:M by
default. Don’t forget to scale your process type to at least 1 to start it!
Conversely, to stop a specific process type, scale it to 0. All existing container(s) in charge of this specific type of process will be stopped and destroyed by the platform.
Removing a Process Type
Removing a process type from an application is done in 3 steps:
- First scale the process type to be removed to 0. You can do this with the CLI or via the dashboard.
- Edit your Procfile and remove the corresponding line. For example, if you
want to remove the
scheduler
process type, locate the line starting withscheduler
and remove it entirely. - Commit your changes and trigger a new deployment.
If you don’t start by scaling down the process type you don’t want anymore, you will encounter the following error message in your application logs:
2022-01-26 10:46:17.855295004 +0000 UTC [worker-1] Task 'worker' has not been found in your 'Procfile'
Developing With a Procfile
To reduce the gap between the development and the production environments, it is important to execute the same processes in both environments.
Several tools exist to fulfill this need:
Example Using foreman
foreman
is a Ruby gem
executing and displaying the output of all the
processes defined in your Procfile. You can install it with the following
command:
gem install foreman
And use it like this:
└> cat Procfile
web: bin/project
worker: bin/project -worker
└> foreman start
17:52:56 web.1 | started with pid 10663
17:52:56 worker.1 | started with pid 10664
17:52:56 web.1 | 2014/12/01 17:52:56 Listen HTTP requests on :5000
17:52:56 worker.1 | 2014/12/01 17:52:56 Starting Asynchronous worker
As you can see, foreman
started a container for each process type defined in
the project’s Procfile (one for the web
process type and another one for the
worker
process type).