
Given https://wiki.openstack.org/wiki/OSSN/OSSN-0046, it seems that this portion of documentation needs to be far more visible on the page. Change-Id: I00f48d23edf5a0844d247a0d1476e9cd31ca84d7
9.6 KiB
Deploying Pecan in Production
There are a variety of ways to deploy a Pecan project to a production environment. The following examples are meant to provide direction, not explicit instruction; deployment is usually heavily dependent upon the needs and goals of individual applications, so your mileage will probably vary.
Note
While Pecan comes packaged with a simple server for development
use (pecan serve
), using a production-ready
server similar to the ones described in this document is very
highly encouraged.
Installing Pecan
A few popular options are available for installing Pecan in production environments:
- Using setuptools. Manage
Pecan as a dependency in your project's
setup.py
file so that it's installed alongside your project (e.g.,python /path/to/project/setup.py install
). The default Pecan project described inquick_start
facilitates this by including Pecan as a dependency for your project. - Using pip. Use
pip freeze
andpip install
to create and install from arequirements.txt
file for your project. - Via the manual instructions found in
Installation
.
Note
Regardless of the route you choose, it's highly recommended that all deployment installations be done in a Python virtual environment.
Disabling Debug Mode
Warning
One of the most important steps to take before deploying a Pecan app
into production is to ensure that you have disabled Debug
Mode, which provides a development-oriented debugging
environment for tracebacks encountered at runtime. Failure to disable
this development tool in your production environment will
result in serious security issues. In your production configuration
file, ensure that debug
is set to False
.
# myapp/production_config.py
app = {
...
'debug': False
}
Pecan and WSGI
WSGI is a Python standard that describes a standard interface between servers and an application. Any Pecan application is also known as a "WSGI application" because it implements the WSGI interface, so any server that is "WSGI compatible" may be used to serve your application. A few popular examples are:
Generally speaking, the WSGI entry point to any Pecan application can
be generated using ~pecan.deploy.deploy
:
from pecan.deploy import deploy
application = deploy('/path/to/some/app/config.py')
Considerations for Static Files
Pecan comes with static file serving (e.g., CSS, Javascript, images) middleware which is not recommended for use in production.
In production, Pecan doesn't serve media files itself; it leaves that job to whichever web server you choose.
For serving static files in production, it's best to separate your concerns by serving static files separately from your WSGI application (primarily for performance reasons). There are several popular ways to accomplish this. Here are two:
Set up a proxy server (such as nginx, cherokee,
cherrypy
, or lighttpd) to serve static files and proxy application requests through to your WSGI application:<HTTP Client> ─── <Production/Proxy Server>, e.g., Apache, nginx, cherokee (0.0.0.0:80) ─── <Static Files> │ ├── <WSGI Server> Instance e.g., mod_wsgi, Gunicorn, uWSGI (127.0.0.1:5000 or /tmp/some.sock) ├── <WSGI Server> Instance e.g., mod_wsgi, Gunicorn, uWSGI (127.0.0.1:5001 or /tmp/some.sock) ├── <WSGI Server> Instance e.g., mod_wsgi, Gunicorn, uWSGI (127.0.0.1:5002 or /tmp/some.sock) └── <WSGI Server> Instance e.g., mod_wsgi, Gunicorn, uWSGI (127.0.0.1:5003 or /tmp/some.sock)
Serve static files via a separate service, virtual host, or CDN.
Common Recipes
Apache + mod_wsgi
mod_wsgi is a popular Apache module which can be used to host any WSGI-compatible Python application (including your Pecan application).
To get started, check out the installation and configuration documentation for mod_wsgi.
For the sake of example, let's say that our project,
simpleapp
, lives at /var/www/simpleapp
, and
that a virtualenv has been
created at /var/www/venv
with any necessary dependencies
installed (including Pecan). Additionally, for security purposes, we've
created a user, user1
, and a group, group1
to
execute our application under.
The first step is to create a .wsgi
file which mod_wsgi
will use as an entry point for your application:
# /var/www/simpleapp/app.wsgi
from pecan.deploy import deploy
application = deploy('/var/www/simpleapp/config.py')
Next, add Apache configuration for your application. Here's a simple example:
<VirtualHost *>
ServerName example.com
WSGIDaemonProcess simpleapp user=user1 group=group1 threads=5 python-path=/var/www/venv/lib/python2.7/site-packages
WSGIScriptAlias / /var/www/simpleapp/app.wsgi
<Directory /var/www/simpleapp/>
WSGIProcessGroup simpleapp
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
For more instructions and examples of mounting WSGI applications using mod_wsgi, consult the mod_wsgi Documentation.
Finally, restart Apache and give it a try.
uWSGI
uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C. It uses the uwsgi protocol, but can speak other protocols as well (http, fastcgi...).
Running Pecan applications with uWSGI is a snap:
$ pip install uwsgi
$ pecan create simpleapp && cd simpleapp
$ python setup.py develop
$ uwsgi --http-socket :8080 --venv /path/to/virtualenv --pecan config.py
or using a Unix socket (that nginx, for example, could be configured to proxy to):
$ uwsgi -s /tmp/uwsgi.sock --venv /path/to/virtualenv --pecan config.py
Gunicorn
Gunicorn, or "Green Unicorn", is a WSGI HTTP Server for UNIX. It’s a pre-fork worker model ported from Ruby’s Unicorn project. It supports both eventlet and greenlet.
Running a Pecan application on Gunicorn is simple. Let's walk through it with Pecan's default project:
$ pip install gunicorn
$ pecan create simpleapp && cd simpleapp
$ python setup.py develop
$ gunicorn_pecan config.py
CherryPy
CherryPy offers a pure Python HTTP/1.1-compliant WSGI thread-pooled web server. It can support Pecan applications easily and even serve static files like a production server would do.
The examples that follow are geared towards using CherryPy as the server in charge of handling a Pecan app along with serving static files.
$ pip install cherrypy
$ pecan create simpleapp && cd simpleapp
$ python setup.py develop
To run with CherryPy, the easiest approach is to create a script in
the root of the project (alongside setup.py
), so that we
can describe how our example application should be served. This is how
the script (named run.py
) looks:
import os
import cherrypy
from cherrypy import wsgiserver
from pecan import deploy
simpleapp_wsgi_app = deploy('/path/to/production_config.py')
public_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'public'))
# A dummy class for our Root object
# necessary for some CherryPy machinery
class Root(object):
pass
def make_static_config(static_dir_name):
"""
All custom static configurations are set here, since most are common, it
makes sense to generate them just once.
"""
static_path = os.path.join('/', static_dir_name)
path = os.path.join(public_path, static_dir_name)
configuration = {
static_path: {
'tools.staticdir.on': True,
'tools.staticdir.dir': path
}
}
return cherrypy.tree.mount(Root(), '/', config=configuration)
# Assuming your app has media on different paths, like 'css', and 'images'
application = wsgiserver.WSGIPathInfoDispatcher({
'/': simpleapp_wsgi_app,
'/css': make_static_config('css'),
'/images': make_static_config('images')
}
)
server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8080), application,
server_name='simpleapp')
try:
server.start()
except KeyboardInterrupt:
print "Terminating server..."
server.stop()
To start the server, simply call it with the Python executable:
$ python run.py