Heroku Flask Tutorial Procfile Meaning
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__)
.
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 Flask
from .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 process
Traceback (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 found
15: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.