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:

  1. First scale the process type to be removed to 0. You can do this with the CLI or via the dashboard.
  2. Edit your Procfile and remove the corresponding line. For example, if you want to remove the scheduler process type, locate the line starting with scheduler and remove it entirely.
  3. 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).


Suggest edits

Procfile

©2024 Scalingo