Deploying Django/Flask App in Production with NGINX Unit and Docker

NGINX unit is a modern take at application server, it supports talking to apps over CGI, WSGI and shared memory incase of statically compiled apps. Unit is open source available at https://unit.nginx.org/
Here are some features:
- Modern Polyglot Application Server
- Supports apps written in popular languages like Go, Python, Java, JavaScript (NodeJS), Ruby and of course good old PHP
- Supports advanced workflow like deploying apps without any downtime, remote configuration management via REST APIs and has ability to run multiple apps (even with different runtime versions!)
- Support for custom routing logic allows easy to A/B testing.
- And it can do TLS in case you’re looking for end-to-end TLS encryption.
Does that sound exciting? let’s look at how you can use Unit to deploy your Django or Flask app on production environment.
Steps for Flask App (we’ll use existing httpbin app which is written using Flask framework and uses gunicorn as application server):
Step 1 : Let’s clone httpbin from Github repo: https://github.com/postmanlabs/httpbin
git clone https://github.com/postmanlabs/httpbin
Step 2: Make following changes in Dockerfile:
-FROM ubuntu:18.04
+FROM nginx/unit:1.18.0-python3.7-CMD ["gunicorn", "-b", "0.0.0.0:80", "httpbin:app", "-k", "gevent"]
+COPY config/config.json /docker-entrypoint.d/
What did we change?
  • Instead of using Ubuntu base image, we’re using nginx/unit image with Python 3.6 runtime.
  • Removed gunicorn command, instead we’ll use configuration file to load application with NGINX Unit.
Step 3: Unit looks for “application” object, adding application object in core.py, here is the diff:
app.config["SWAGGER"] = {"title": "httpbin.org", "uiversion": 3}+# NGINX Unit looks for application object
+application = app
+
 template = {
     "swagger": "2.0",
     "info": {
Step 4 : Adding Unit configuration file (config/config.json):
{
       "listeners":{
          "*:80":{
             "pass":"applications/httpbin"
          }
       },
       "applications":{
          "httpbin":{
             "type":"python 3",
             "path":"/httpbin",
             "module":"httpbin"
       }
    }
 }
This file contains instruction to listen to port 80 on all interfaces and routing any traffic on port 80 to our flask app “httpbin”
“httpbin” section contains path to project directory and module with contains flask “application” object.
And finally, let’s build the docker image with httpbin + nginx unit:
docker build -t httpbin-unit .
Result:
When the container is started, Unit will look for any configuration file in /docker-entrypoint.d/*. Since we have put our configuration file there, Unit will load the configuration from /docker-entrypoint.d/config.json and reconfigure itself to load our application.
Here is the Github commit link for all these changes and ready to use httpbin + unit image on DockerHub
Hope this is useful to integrate Unit with your Flask apps, I’ve done this using real app instead of simple “hello world” Flask app :-)

Comments