Embedding an application in uWSGI
Starting from uWSGI 0.9.8.2, you can embed files in the server binary. Thesecan be any file type, including configuration files. You can embed directoriestoo, so by hooking the Python module loader you can transparently importpackages, too. In this example we’ll be embedding a full Flask project.
Step 1: creating the build profile
We’re assuming you have your uWSGI source at the ready.
In the buildconf
directory, define your profile – let’s call it flask.ini:
- [uwsgi]
- inherit = base
- main_plugin = python
- bin_name = myapp
- embed_files = bootstrap.py,myapp.py
myapp.py
is a simple flask app.
- from flask import Flask
- app = Flask(__name__)
- app.debug = True
- @app.route('/')
- def index():
- return "Hello World"
bootstrap.py
is included in the source distribution. It will extend the python import subsystem to use files embedded in uWSGI.
Now compile your app-inclusive server. Files will be embedded as symbols in theexecutable. Dots and dashes, etc. in filenames are thus transformed tounderscores.
- python uwsgiconfig.py --build flask
As bin_name
was myapp
, you can now run
- ./myapp --socket :3031 --import sym://bootstrap_py --module myapp:app
The sym://
pseudoprotocol enables uWSGI to access the binary’s embeddedsymbols and data, in this case importing bootstrap.py directly from the binaryimage.
Step 2: embedding the config file
We want our binary to automatically load our Flask app without having to pass a long command line.
Let’s create the configuration – flaskconfig.ini:
- [uwsgi]
- socket = 127.0.0.1:3031
- import = sym://bootstrap_py
- module = myapp:app
And add it to the build profile as a config file.
- [uwsgi]
- inherit = default
- bin_name = myapp
- embed_files = bootstrap.py,myapp.py
- embed_config = flaskconfig.ini
Then, after you rebuild the server
- python uwsgiconfig.py --build flask
you can now simply launch
- ./myapp
- # Remember that this new binary continues to be able to take parameters and config files:
- ./myapp --master --processes 4
Step 3: embedding flask itself
Now, we are ready to kick asses with uWSGI ninja awesomeness. We want a singlebinary embedding all of the Flask modules, including Werkzeug and Jinja2,Flask’s dependencies. We need to have these packages’ directories and thenspecify them in the build profile.
- [uwsgi]
- inherit = default
- bin_name = myapp
- embed_files = bootstrap.py,myapp.py,werkzeug=site-packages/werkzeug,jinja2=site-packages/jinja2,flask=site-packages/flask
- embed_config = flaskconfig.ini
Note
This time we have used the form “name=directory” to force symbols toa specific names to avoid ending up with a clusterfuck likesite_packages_flaskinitpy
.
Rebuild and re-run. We’re adding –no-site when running to show you that theembedded modules are being loaded.
- python uwsgiconfig.py --build flask
- ./myapp --no-site --master --processes 4
Step 4: adding templates
Still not satisfied? WELL YOU SHOULDN’T BE.
- [uwsgi]
- inherit = default
- bin_name = myapp
- embed_files = bootstrap.py,myapp.py,werkzeug=site-packages/werkzeug,jinja2=site-packages/jinja2,flask=site-packages/flask,templates
- embed_config = flaskconfig.ini
Templates will be added to the binary… but we’ll need to instruct Flask onhow to load templates from the binary image by creating a custom Jinja2template loader.
- from flask import Flask, render_template
- from flask.templating import DispatchingJinjaLoader
- class SymTemplateLoader(DispatchingJinjaLoader):
- def symbolize(self, name):
- return name.replace('.','_').replace('/', '_').replace('-','_')
- def get_source(self, environment, template):
- try:
- import uwsgi
- source = uwsgi.embedded_data("templates_%s" % self.symbolize(template))
- return source, None, lambda: True
- except:
- pass
- return super(SymTemplateLoader, self).get_source(environment, template)
- app = Flask(__name__)
- app.debug = True
- app.jinja_env.loader = SymTemplateLoader(app)
- @app.route('/')
- def index():
- return render_template('hello.html')
- @app.route('/foo')
- def foo():
- return render_template('bar/foo.html')
POW! BIFF! NINJA AWESOMENESS.