• How to Configure NGINX for a Flask Web Application
  • By PatrickSoftware
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: lsvih
  • Proofreader: GanymedeNil

How do I configure Nginx for a Flask Web application

Introduction to the

In this article, I’ll explain what Nginx is and how to configure Nginx for a Flask Web application. This article is part of a series called Deploying Flask. I’ve found several articles on Nginx and its configuration, but I’d like to go into more detail about how to use Nginx to serve Flask Web applications and how to configure them for them. The Nginx configuration file is a bit confusing because most of the documentation simply lists a configuration file without explaining what is done in each step of the configuration. Hopefully, this article gave you a clear understanding of how to configure Nginx for your applications.

What is Nginx?

The Nginx (pronounced “engine-x”) website provides a brief description of the tool:

Nginx is a free, open source, high-performance HTTP server and reverse proxy that can also be used as an IMAP/POP3 proxy server. Nginx is known for its high performance, stability, rich functionality, simple configuration, and low resource consumption.

We can expand on this description… Nginx is a server that handles HTTP requests for your Web applications. For typical Web applications, Nginx can be configured to perform the following operations for HTTP requests:

  • Reverse proxy the request to an upstream server (such as Gunicorn, uWsgi, Apache, etc.).
  • Services static resources (Javascript files, CSS files, images, documents, static HTML files).

Nginx also provides load balancing, which allows multiple upstream servers to service requests, but this feature is not covered in this article.

The following diagram shows how Nginx provides service for Flask Web applications:

Nginx handles Http requests from the Internet, such as users of your application. Depending on how you configure Nginx, it can directly serve and return static content (Javascript files, CSS files, images, documents, static HTML files) to the requesting source. In addition, it can reverse proxy requests to WSGI (Web Server Gateway Interface) so you can generate dynamic content (HTML) in your Flask Web application and return it to the user.

The diagram above assumes that the user is using Docker, but the configuration of Nginx without Docker is very similar (except that the container concept in the diagram is omitted).

Why do you need Nginx and Gunicorn?

Nginx, as an HTTP server, is used in many applications: lists. It provides a lot of functionality, but it doesn’t directly serve Flask applications. And Gunicorn can do that. Nginx takes the HTTP request and passes it to Gunicorn for your Flask application to process (such as the route you defined in View.py). Gunicorn is a WSGI server that can process HTTP requests and route them to any PYTHON application that supports WSGI (Flask, Django, Pyramid, etc.).

Structure of the Nginx configuration file

Note: this article uses Nginx v1.11.3. The location of the configuration file will vary depending on your version of Nginx, such as /opt/ Nginx /conf/.

The configuration file structure will vary slightly depending on how you install and use Nginx. Most configuration structures are as follows:

Structure of 1

If you are using Nginx compiled from source code or an official Docker image, then the configuration file is in /etc/nginx/and the main configuration file is /etc/nginx/nginx.conf. The bottom line of /etc/nginx/nginx.conf loads the rest of the configuration file content in /etc/nginx/conf.d/ :

  • include /etc/nginx/conf.d/*.conf;

Structure of 2

If you installed Nginx through a package manager (such as Ubuntu apt-get), then your /etc/nginx/will have the following two subdirectories:

  • Sites-available – Contains multiple configuration files for multiple sites.
  • Sites-enabled – Contains a soft link to a configuration file in the Sites-available directory.

These two directories inherit from Apache and will be applied to the Nginx configuration.

Since my Flask application uses a Docker deployment, I’ll focus on structure 1 above in this article.

Nginx configuration

The top-level configuration file for Nginx is nginx.conf. Nginx accepts multiple levels of configuration files, which also allows users to configure flexibly for their own applications. For details about parameters in the configuration file, see the Nginx official documentation.

In Nginx, configuration blocks organize configuration parameters. Here are the configuration blocks we will cover in this article:

  • Main – defined in nginx.conf (all parameters that are not part of the configuration block are in the Main block)
  • Events – defined in nginx.conf
  • Http – defined in nginx.conf
  • Server – Defined inapplication_name.conf

Splitting these configuration blocks into separate files allows you to define the high-level configuration of Nginx in nginx.conf and to define the virtual host or server parameters for your application in other *.conf files.

Nginx. conf Details

The default nginx.conf file that comes with Nginx installation can be used for the initial configuration of most servers. Let’s take a closer look at the contents of nginx.conf and think about how to extend the default Settings here.

The Main part

The main configuration block of nginx.conf (that is, the parameters that are not in the configuration block) is:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
Copy the code

The first parameter (user) defines the owner of the Nginx server and the user who runs it. When Nginx is run through a Docker container, the default values are sufficient.

The second parameter (worker_Processes) defines the number of worker processes. The recommended default value for this parameter is the number of kernels currently used by the server. For basic virtual private servers (VPS), the default value of 1 is a good choice. You can increase this number as you expand VPS performance.

The third parameter (error_log) defines where the error log resides on the file system, and an additional parameter can be defined to specify the minimum error level to log. Use the default value for this parameter.

The fourth parameter (PID) defines the file location where the PID of the main Nginx process is stored. Use the default value for this parameter.

Events configuration block

The Events configuration block defines a number of parameters that affect connection processing. This is also the first configuration block in the nginx.conf file:

events {
    worker_connections  1024;
}
Copy the code

There is a single parameter (worker_connections) in this configuration block, which defines the maximum number of concurrent connections that a worker process can open. The default value defines a total of 1024 connections available and does not need to be changed (but you need to count the number of connections the user has requested to the site and the WSGI server).

The HTTP configuration block

The HTTP configuration block defines some parameters about how Nginx handles HTTP Web traffic. This is the second configuration block in the nginx.conf file:

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush on;

    keepalive_timeout  65;

    #gzip on;

    include /etc/nginx/conf.d/*.conf;
}
Copy the code

The first argument (include) specifies the configuration file to be imported. In this case, the mime.types file located in /etc/nginx/defines the various file types supported by Nginx. This parameter should remain the default value.

The second argument (default_type) specifies the type of file that is returned to the user by default. Flask applications return dynamically generated HTML files, so change this parameter to default_type text/ HTML;

The third parameter (log_format) specifies the log format and should remain the default.

The fourth parameter (access_log) specifies where the Nginx log is accessed and should remain the default.

The fifth parameter (send_file) and the sixth parameter (tcp_nopush) are a little more complicated. See tuning Nginx for details on these parameters, including tcp_nodelay. Since we intend to use Nginx to pass static content, we can set these parameters like this:

    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;
Copy the code

The seventh parameter (keepalive_timeout), which defines the timeout period to stay connected to the client, should remain the default.

The eighth parameter (gzip) defines how to use the GZIP compression algorithm to reduce the amount of data transferred. Although the amount of data is reduced, it also increases the performance cost of the compression process for the platform, so it is left at its default value (off).

The ninth and final parameter (include) defines the other.conf configuration file under /etc/nginx/conf.d/. We will now use these configuration files to define the static content server and the reverse proxy for the WSGI server.

The final configuration of nginx.conf

In addition to the default nginx.conf Settings, we need to adjust (and comment) some parameters as needed. Here is the final version of nginx.conf:

# Define the user that will own and run the Nginx server
user  nginx;
# Define the number of worker processes; recommended value is the number of
# cores that are being used by your server
worker_processes  1;

# Define the location on the file system of the error log, plus the minimum
# severity to log messages for
error_log  /var/log/nginx/error.log warn;
# Define the file that will store the process ID of the main NGINX process
pid        /var/run/nginx.pid;

# events block defines the parameters that affect connection processing.
events {
   # Define the maximum number of simultaneous connections that can be opened by a worker process
   worker_connections  1024;
}

# http block defines the parameters for how NGINX should handle HTTP web traffic
http {
   # Include the file defining the list of file types that are supported by NGINX
   include       /etc/nginx/mime.types;
   # Define the default file type that is returned to the user
   default_type  text/html;

   # Define the format of log messages.
   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

   # Define the location of the log of access attempts to NGINX
   access_log  /var/log/nginx/access.log  main;

   # Define the parameters to optimize the delivery of static content
   sendfile        on;
   tcp_nopush     on;
   tcp_nodelay    on;

   # Define the timeout value for keep-alive connections with the client
   keepalive_timeout  65;

   # Define the usage of the gzip compression algorithm to reduce the amount of data to transmit
   #gzip on;

   # Include additional parameters for virtual host(s)/server(s)
   include /etc/nginx/conf.d/*.conf;
}
Copy the code
Configure Nginx for static content deployment and reverse proxy

If you look at the default/etc/nginx/conf. G/default conf, you can see it provides a simple server configuration, and gave many uncomment can use the optional configuration. We won’t go through the configuration in this file in turn, but will go directly to the key parameters that will be useful for us to deploy static content and WSGI reverse proxies. The following is the recommended application_name. Conf configuration:

# Define the parameters for a specific virtual host/server
server {
   # Define the directory where the contents being requested are stored
   # root /usr/src/app/project/;

   # Define the default page that will be served If no page was requested
   # (ie. if www.kennedyfamilyrecipes.com is requested)
   # index index.html;

   # Define the server name, IP address, and/or port of the server
   listen 80;
   # server_name xxx.yyy.zzz.aaa

   # Define the specified charset to the “Content-Type” response header field
   charset utf-8;

   # Configure NGINX to deliver static content from the specified folder
   location /static {
       alias /usr/src/app/project/static;
   }

   # Configure NGINX to reverse proxy HTTP requests to the upstream server (Gunicorn (WSGI server))
   location / {
       # Define the location of the proxy server to send the request to
       proxy_pass http://web:8000;

       # Redefine the header fields that NGINX sends to the upstream server
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

       # Define the maximum file size on file uploadsclient_max_body_size 5M; }}Copy the code

The server configuration block defines parameters for a specific virtual host or server. Typically for a single Web application that you deploy on a VPS.

The first parameter (root) defines where the requested content is stored. When Nginx receives a user request, it looks in this directory. Since it is defined in the default “/” path, you can comment out this unnecessary parameter.

The second parameter (index) defines the request is not specified page (for example, www.kennedyfamilyrecipes.com) have been the default page. Since we are using dynamic content generated by the Flask Web application, we need to comment out this parameter.

The first two parameters (root and index) are included in this configuration file and can be used in Nginx configurations in some cases.

The third parameter (server_name) and fourth parameter (LISTEN) need to be used together. If your Web application is already deployed, you need to set these parameters to:

Server {... Listen 192.241.229.181; ... }Copy the code

In addition to www.kennedyfamilyrecipes.com if you want to deploy another Flask application blog.kennedyfamilyrecipes.com, then you will need to “server” configuration block apart, Set user_name and LISTEN respectively:

server { listen 80; server_name *.kennedyfamilyrecipes.com; . . . } server { listen 80; server_name blog.kennedyfamilyrecipes.com; ...}Copy the code

Nginx will select the “server_name” that best matches the request. Meaning of “blog.kennedyfamilyrecipes.com” requests will be priority to match “blog.kennedyfamilyrecipes.com” instead of “* kennedyfamilyrecipes.com”.

The fifth parameter (charset) defines the character set value of the response header “content-type” and should be set to “UTF-8”.

The first “location” configuration block defines the static content that Nginx needs to deliver at the following locations:

  location /static {
       alias /usr/src/app/project/static;
   }
Copy the code

The Location configuration block defines how to process the REQUEST’S URI (the domain name or part after the IP and port number). In the first location configuration block (/ static), we define the Nginx will deal with a request from the www.kennedyfamilyrecipes.com/static/, Retrieval in the/usr/SRC/app/project/static files in the directory. Request, for example, www.kennedyfamilyrecipes.com/static/img/img_1203.jpg will return in the/usr/SRC/app/project/static/img/img_1203. JPG image file. If the file does NOT exist, a 404 error code (NOT FOUND) is returned to the user.

The second Location configuration block (“/”) defines the reverse proxy. This location configuration block defines how Nginx passes requests to the WSGI (Gunicorn) server where our Flask application interface resides. Take a closer look at each of the parameters:

   location / {
       proxy_pass http://web:8000;
       proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       client_max_body_size 5M;
   }
Copy the code

The first parameter (proxy_pass) defines the location of the proxy server that receives the forward request. Use this if you want to forward the request to the local server:

proxy_pass http://localhost:8000/;
Copy the code

If you want to forward the request to a specific Unix socket (such as the Gunicorn server running on the same machine as Nginx), you can use:

proxy_pass http://unix:/tmp/backend.socket:/
Copy the code

If you are running Nginx in a Docker container and want to communicate with Gunicorn in the container, you can use the name of the container running Gunicorn directly:

proxy_pass http://web:8000;
Copy the code

The second parameter (proxy_pass_header) allows you to redefine the header of the request to an upstream server such as Gunicorn. This parameter can be set four times:

  • Nginx server name and port (Host $Host)
  • This is the mode of the original client request (for example, HTTP or HTTPS). (x-Forwarded-proto $scheme)
  • $remote_addr (X- real-ip $remote_addr)
  • (X- forwarded_for $proxy_add_x_forwarded_for)

The third parameter (client_max_body_size) defines the maximum size allowed for file uploads and is important for Web applications that need to upload files. Since the image size is usually within 2 MB, setting 5 MB here should satisfy almost any image.

conclusion

This article explains what an Nginx server is and how to configure it for a Flask application. Nginx is a key component of most Web applications, providing users with static content, reverse proxy requests to an upstream server (WSGI in our Flask Web application), and load balancing (not mentioned in this article). Hopefully, after reading this article, you will find it easier to understand Nginx configuration!

Reference data

How to Configure NGINX (Linode)

NGINX Wiki

NGINX Pitfalls and Common Mistakes

How to Configure the NGINX Web Server on a VPS (DigitalOcean)

Understanding NGINX Server and Location Block Selection Algorithms (DigitalOcean)

NGINX Optimization: Understanding sendfile, tcp_nodelay, and tcp_nopush


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.