Skip to content

Latest commit

 

History

History

nginx-wsgi

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

One-Off Coder Logo

Purpose

The purpose of this project is to demonstrate the ability to run nginx, gunicorn and flask together in a Docker container.

Why is this demonstration even important?

Robust deployment

In any case of deployment (especially production deployment), using flask alone to serve request is not the right thing to do. Typically, gunicorn is placed in front of flask to receive the request; gunicorn helps out primarily by scaling out the flask service (see here and here). Additionally, gunicorn itself is inadequate and nginx comes into play for better performance such as serving dynamic or static content; in the case of dynamic content, nginx will delegate this to gunicorn; in the case of static content, nginx will do better at serving those content back. There are many reported performance problems with using flask alone, and this demonstration shows a template containerized approach you may adapt to properly deploy your flask application.

Multiple services

One complication comes with having nginx and gnunicorn that have to both run at container startup. In Docker, you can only have one CMD command. Thus, you can only run either nginx or gnunicorn.

CMD ["gunicorn", "-b", "unix:app.sock ", "-w", "4", "--chdir", "/app", "app:app"]

or

CMD ["nginx", "-g", "daemon off;"]

You can use the single CMD with && or ; to start both services. However, that seems a bit undisciplined as these are services, and also, take a look at how the array passed to CMD grows. (I'm not even sure if the following will work; besides, which service will be in the foreground and which in the background?).

CMD ["gunicorn", "-b", "unix:app.sock ", "-w", "4", "--chdir", "/app", "app:app", ";", "nginx", "-g", "daemon off;"]

The best approach is to use supervisor to control the services. What I like about supervisor is that it is easy to configure and it can restart failed services. Futhermore, both services are now in the foreground (you are able to monitor logging to the console for debugging purpose).

Docker Hub

Image

Docker

Build it.

./build.sh

Run it.

docker run -it -p 80:80 --rm nginx-wsgi:local

Observe it.

References

Take a Look!

Check out John Papa. He's got some good philosophical approaches to creating awesome software.

Citation

@misc{oneoffcoder_nginx_wsgi_2019, 
title={Docker container show how to run a Flask application behind gunicorn and nginx}, 
url={https://github.com/oneoffcoder/docker-containers/tree/master/nginx-wsgi}, 
journal={GitHub},
author={One-Off Coder}, 
year={2019}, 
month={Jul}}