Configure Nginx to Serve a Flask App

Jun 16, 2019

Deploying your web application with NGINX

I was so stoked the first time I'd managed to build a web application. It was solving an actual problem real people were facing. It was love at first site between me and infinite scroll data tables.  

Then I had to deploy my application, and several other applications on the same server, and I was less than pleased!

Writing all the code was such a big hurtle for me, and then I had to figure out the deployment feature too. Luckily, I worked with a great IT department and they were able to point me towards some great resources. These days I do all my development in docker and keep as a library of templates for deploying my projects.

Flask + NGINX

These days I mostly use Traefik to do my load balancing and proxy passes, but its important to understand the fundamentals before you go throwing around all kinds of mostly optional prettiness. 

In this example I am deploying a Python Flask application using Nginx, but understanding the concepts behind deploying will make your life much easier!

 

Spinning up your Flask Service

This post isn't going to cover how to actually create your Flask application, but the ​Flask site has some great tutorials!​​​ If you would like to see a post that goes into more detail on building the Flask image please check out Develop a Python Flask Application with Docker Series.

As a quick note I use Flask as an example, but in the wonderful world of APIs and web servers it doesn't really matter. You could deploy just about any web application using any framework or language, as long as you know the port, and how (or if) to pass in a prefix argument (more on that later!).

Project Layout

I like to keep all my applications separate. In this example I have a single flask application, being served on port 5000 in the container. There is a get method on the flask service at / that returns a status ok, and a post method at /health that returns whatever you give to it.

From there, I have two separate docker-compose services. One servers the flask application at its root, and one serves it from /api. Whatever set up you choose is going to depend on your exact situation, and probably how many services you are trying to serve from a single domain.

Remember, if you are using docker-compose, your host name matches the service name, and the port matches the port the application is using within it's container, NOT its exposed port!

NGINX Option 1: Serve from the Root

If you only have a single service on a single host you will probably go for this option. It's the simplest of the options, which is always good! This location block should be INSIDE of your server block.

    ## proxy_pass http://$DOCKER_COMPOSE_SERVICE_NAME:5000/;
    ## proxy_pass address HAS to have the trailing / to work
    location / {
        proxy_set_header   Host                 $host;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto    $scheme;
        proxy_set_header Host $http_host;

        proxy_pass http://flask-app-server:5000/;
    }

NGINX Option 1: Serve from A Prefix /api

If you have multiple services on a single host you will probably go with this option, which is to serve your application under a path prefix. This location block should be INSIDE of your server block.

As a quick note, most flask applications I've worked with have been fine out of the box. Many other applications though will need for you to pass in a --prefix argument on startup, or do regular expressions magic in order to get the url passed through correctly. I find its easiest to just find the prefix argument in your web server of choice and use that.  

    location /api {
        proxy_set_header   Host                 $host;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto    $scheme;
        proxy_set_header Host $http_host;

        proxy_pass http://flask-app-server:5000/;
    }
 

Bioinformatics Solutions on AWS Newsletter 

Get the first 3 chapters of my book, Bioinformatics Solutions on AWS, as well as weekly updates on the world of Bioinformatics and Cloud Computing, completely free, by filling out the form next to this text.

Bioinformatics Solutions on AWS

If you'd like to learn more about AWS and how it relates to the future of Bioinformatics, sign up here.

We won't send spam. Unsubscribe at any time.