Post

Using Nginx for Production ready Flask app with uWSGI

After creating many Flask applications using Python, the thing that always made me sad is the below ‘WARNING’ message. But since I was doing it mostly for my learning, I didn’t bother much about the warning as long as the flask application worked.

1
2
3
4
5
6
7
8
\* Serving Flask app "app" (lazy loading)  
\* Environment: production

**WARNING: This is a development server. Do not use it in a production deployment.**

   Use a production WSGI server instead.  
 \* Debug mode: off  
 \* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)

For one of our project we created a Python Flask application and it all worked wonderfully well, but only on my local system. To make it a production ready API service, I had to explore more about serving the application.

Our project has multiple microservices which run as Docker containers orchestrated using Kubernetes.

The aim is to make the Flask application run by Nginx by using uWSGI. And all these should run as seperate Docker containers.

The below is the tree structure for our sample application with flask and nginx folders for each container.

Tree structure of the application

Let’s dive into the program step by step.

app.py would be your working Flask application. In our case it would just print “Hello World”. This would be the only change that you need to do and replace it with your own Flask application.

1
2
3
4
5
6
7
8
9
from flask import Flask  
app = Flask(__name__)

@app.route("/")  
def home():  
   return("Hello World")

if __name__ == "__main__":  
   app.run()

The Dockerfile for the flask application which installs the needed libraries and runs the uwsgi app.

1
2
3
4
5
FROM python:3.7.3-stretch  
WORKDIR /app  
ADD . /app  
RUN pip install -r requirements.txt  
CMD \["uwsgi","app.ini"\]

The uwsgi configurations are maintained in the app.ini file which calls the app.py file. In case you are using a different python file or app name, it needs to be updated here.

1
2
3
4
5
6
7
8
9
10
11
[uwsgi]  
wsgi-file = app.py  
callable = app  
processes = 4  
threads = 2  
callable = app  
socket = :5000  
master = true  
chmod-socket = 660  
vacuum = true  
die-on-term = true

The requirements.txt file would hold all the needed libraries.

1
2
3
4
5
6
7
Click==7.0  
Flask==1.0.3  
itsdangerous==1.1.0  
Jinja2==2.10.1  
MarkupSafe==1.1.1  
uWSGI==2.0.18  
Werkzeug==0.15.4

We are done with everything that is to be done for our Flask Docker container. Now we need to prepare our Nginx Docker container to run the flask application.

First creating a Dockerfile to run the Nginx. If your project already has an Nginx Docker service, update the configuration file to add the changes for the flask application.

1
2
3
4
5
FROM nginx

RUN rm /etc/nginx/conf.d/default.conf

COPY nginx.conf /etc/nginx/conf.d/

Now we need to have our configuration in our nginx server to run the flask container. The Nginx server would listen at port 8080 and call the flask container at port 5000.

1
2
3
4
5
6
7
8
server {

    listen 8080;  
    location / {  
        include uwsgi_params;  
        uwsgi_pass flask:5000;  
     }  
}

Now the final part is to create a docker compose file to run our application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3"

services:  
  flask:  
    build: ./flask  
    container_name: flask  
    restart: always  
    expose:  
      - 5000  
  nginx:  
    build: ./nginx  
    container_name: nginx  
    restart: always  
    ports:  
      - "8080:8080"

Once all the files are in place, it is time to run the services and see if it is working. Go to the main folder and run the docker compose.

1
docker-compose up

Our nginx server is running, which listens to port 8080 to make any calls to the flask application.

1
[http://localhost:8080](http://localhost:8080)

http://localhost:8080

Voila! It worked.

The entire application is available at https://github.com/ksashok/Flask-Nginx-uwsgi

This post is licensed under CC BY 4.0 by the author.