Heroku Flask Tutorial Procfile Meaning Heroku Flask Tutorial Procfile Meaning heroku heroku

Heroku Flask Tutorial Procfile Meaning


tl;dr: hello refers to hello.py and app refers to app = Flask(__name__)


The mentioned Heroku tutorial is no more available, however Gunicorn's doc gives a good minimal example :

Example with the test app:

def app(environ, start_response):    """Simplest possible application object"""    data = b'Hello, World!\n'    status = '200 OK'    response_headers = [        ('Content-type', 'text/plain'),        ('Content-Length', str(len(data)))    ]    start_response(status, response_headers)    return iter([data])

You can now run the app with the following command:

$ gunicorn --workers=2 test:app


Let's try, my test-directory looks like this :

(.venv) 14:41 ~/testgunicorn % tree.├── requirements.txt└── testpkg    ├── __init__.py    └── testfile.py

__init__.py :

from flask import Flaskfrom .testfile import app

testfile.py :

#!/usr/bin/env python3# -*- coding: utf-8 -*-def app(environ, start_response):    """Simplest possible application object"""    data = b'Hello, World!\n'    status = '200 OK'    response_headers = [        ('Content-type', 'text/plain'),        ('Content-Length', str(len(data)))    ]    start_response(status, response_headers)    return iter([data])

Wrong calling :

(.venv) 14:41 ~/testgunicorn % gunicorn testfile:app         [2018-08-24 14:41:44 +0200] [27248] [INFO] Starting gunicorn 19.9.0[2018-08-24 14:41:44 +0200] [27248] [INFO] Listening at: http://127.0.0.1:8000 (27248)[2018-08-24 14:41:44 +0200] [27248] [INFO] Using worker: sync[2018-08-24 14:41:44 +0200] [27251] [INFO] Booting worker with pid: 27251[2018-08-24 14:41:44 +0200] [27251] [ERROR] Exception in worker processTraceback (most recent call last):  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker    worker.init_process()  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 129, in init_process    self.load_wsgi()  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi    self.wsgi = self.app.wsgi()  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi    self.callable = self.load()  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load    return self.load_wsgiapp()  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp    return util.import_app(self.app_uri)  File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/util.py", line 350, in import_app    __import__(module)ModuleNotFoundError: No module named 'testfile'[2018-08-24 14:41:44 +0200] [27251] [INFO] Worker exiting (pid: 27251)[2018-08-24 14:41:44 +0200] [27248] [INFO] Shutting down: Master[2018-08-24 14:41:44 +0200] [27248] [INFO] Reason: Worker failed to boot.zsh: exit 3     gunicorn testfile:app    

Good callings :

(.venv) 14:43 ~/testgunicorn % gunicorn testpkg:app [2018-08-24 14:43:56 +0200] [27302] [INFO] Starting gunicorn 19.9.0[2018-08-24 14:43:56 +0200] [27302] [INFO] Listening at: http://127.0.0.1:8000 (27302)[2018-08-24 14:43:56 +0200] [27302] [INFO] Using worker: sync[2018-08-24 14:43:56 +0200] [27305] [INFO] Booting worker with pid: 27305^C(…)(.venv) 15:03 ~/testgunicorn % cd testpkg    (.venv) 15:03 fred@susa ~/git/ocp7/testpkg % gunicorn testfile:app[2018-08-24 15:03:22 +0200] [27494] [INFO] Starting gunicorn 19.9.0[2018-08-24 15:03:22 +0200] [27494] [INFO] Listening at: http://127.0.0.1:8000 (27494)[2018-08-24 15:03:22 +0200] [27494] [INFO] Using worker: sync[2018-08-24 15:03:22 +0200] [27497] [INFO] Booting worker with pid: 27497^C(…)

Then for this Procfile :

web: gunicorn hello:app --log-file=-

Does hello refer to the hello() function or the hello.py script?

To the hello.py script

Depending on the meaning of that, what does the whole Procfile statement mean?

Heroku's Procfile format documentation says :

A Procfile declares its process types on individual lines, each with the following format:

<process type>: <command>

  • <process type> is an alphanumeric name for your command, such as web, worker, urgentworker, clock, and so on.
  • <command> indicates the command that every dyno of the process type should execute on startup, such as rake jobs:work.

The --logfile=- option seems to be deprecated, I did not find anything about it in documentation and if I use it I get this error :

(.venv) 15:34 ~/testgunicorn % heroku local web[WARN] No ENV file found15:34:30 web.1   |  usage: gunicorn [OPTIONS] [APP_MODULE]15:34:30 web.1   |  gunicorn: error: unrecognized arguments: --logfile=-15:34:30 web.1   Exited with exit code 2

According to this answer it was an option for logging in Heroku's stdout.


The ProcFile contains the command line for starting your application on heroku. The full documentation can be found here: https://devcenter.heroku.com/articles/procfile

In this case it is telling heroku to use the app variable (your constructed flask app) in the hello module with gunicorn and to start a web process (one that can handle http requests). There are other process types you can specify such as background workers.

Your flask application object is a WSGI application, and can be run using any WSGI server. Gunicorn is just one of the choices on heroku.


1-According to Heroku doc section Procfile format

web: gunicorn hello:app  

is a <process type>: <command> pattern

2- web is therefore the <process type>. According to the same documentation: "A Heroku app’s web process type is the only process type that can receive external HTTP traffic from Heroku’s routers. If your app includes a web server, you should declare it as your app’s web process."

3- Now the <command> part:

gunicorn hello:app  

If you look in the gunicorn doc section basic usage you will see that a typical command for gunicorn is

$ gunicorn [OPTIONS] APP_MODULE

Where APP_MODULE is of the pattern $(MODULE_NAME):$(VARIABLE_NAME).

So in your example hello refers $(MODULE_NAME) that is hello.py. Note that it can be a full dotted path if necessary. In the same way app refers to a WSGI callable $(VARIABLE_NAME) that should be found in the specified hello module and actually defined when you instantiated the Flask class:app = Flask(__name__).