With the help of this tutorial, you will be able to deploy your application with the help of the web server and (reverse proxy) in my opinion easier to handle and optimal nginx and the Gunicorn WSGI server, so let’s hit it!
NOTE: you can use your WSGI server with any other web server for example like Apache2 but that if you have to manually configure the apache file.conf with the virtualhost and give the correct paths to your local app which can be somewhat tedious and complex, ( also gunicorn accepts most web servers not only ngnix), therefore we will use nginx 🙂
Well I will make a quick and brief explanation about the concept of nginx and gunicorn:
What is Nginx?
It is a web server and reverse proxy, it does not translate requests to WSGI its characteristics are:
- Take care of domain name routing (decide where requests should go, or if an error response is in order)
- Serve static files
- Handle lots of requests coming in at once
- Handle slow clients
- Forwards requests which need to be dynamic to Gunicorn
- Terminate SSL (https happens here)
- Save computing resources (CPU and memory) compared to your Python code
Now, what is gunicorn and how does it work?
Translate the requests given by nginx in such a way that our application can understand these received requests and that my python3 code runs normally, how does it work … well gunicorn executes a group of processes / threads, it translates the requests that come from nginx to be compatible with WSGI, translate these WSGI responses from the app into appropriate HTTP responses, finally, as noted at the beginning, it can communicate with many web servers.
Here’s a diagram illustrating how NGINX fits into a Flask web application:

Now, let’s put our hands in the dough!
The first step to install the necessary packages on our server
Note: (the example server, its security groups as inbound rule has http, ssh, https ports as inbound rules and as outbound rules all traffic)
Like this:
In this case I am using python3, therefore the packages to install, are as follows:
$ sudo apt-get update
$ sudo apt-get install python3-pip python3-dev nginx
$ pip3 install gunicorn
Note: in this tutorial we will not use virtualenv
Well, in this tutorial I will not expose my application since it is a bit long, we will do it with a very simple application that only shows the user a message on the screen and that’s it.
name_file: my_app.py
from flask import Flask
app = Flask(__name__)
@app.route(“/”)
def hello():
return "HELLO FLASK!"
if name == “__main__”:
app.run(host="0.0.0.0" port=5000) # our application will run with this port and this host
of course we can continue executing (as an optional step) our application locally with the command:
python3 -m my_app
NOW, we have reached a very important point in this tutorial, and that is to give the entry point of our application to Gunicorn3 also, We’ll also specify the interface and port to bind to so that it will be started on a publicly available interface like this:
gunicorn3 –bind 0.0.0.0:5000 my_app:app
This step takes a little time, if in this step a very common error like the one that happened to me occurs, and it is error [98] the address is already in use in these cases you should look at your ports that are being listened to and the processes which you consider to be the cause of this annoying process!
The next step is, create a systemd unit file that allows the Ubuntu boot system to start Gunicorn automatically and serve up our Flask application every time the server starts.
In a few words, what we will do is create a file.service that we will execute every time we add changes to our application in the code, for example, what we would do would be to restart this service is that simple!
to do this we will move to this path: /etc/systemd/system/
and here we are going to create our .service in this case I will call it myApp.service so what goes here?
[Unit]
Description=Hi, there!
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu
ExecStart=/home/ubuntu/gunicorn –workers 3 –bind unix:myproject.sock -m 007 my_app:app
[Install]
WantedBy=multi-user.target
in the previous snippet
We will tell you to start 3 worker processes which can vary. We will also tell you to create and link to a Unix socket file within our project directory called myproject.sock. We will set a umask value of 007 so that the socket file is created giving owner and group access, while restricting other access. Finally, we need to pass the filename of the WSGI entry point and the callable Python inside.
Now we can start the Gunicorn service we created and enable it to start on boot:
sudo systemctl start myApp
sudo systemctl enable myApp
The next step is, configure Nginx for proxy requests!
well at this moment our application must be running with gunicorn waiting for requests in the socket file in the project directory.
Ok now we have our socket but we also need to pass the web requests! we will do this making some small additions to the config file.
To do this we will move to next path: /etc/nginx/sites-available/
here we create a file with whatever name you want there is no mess I will put: myApplication! so here what we will do is tell NGINX to listen on the default port 80. And we will also tell you which ip or domain if you have even better from our server
like this with the unit server:
server {
listen 80;
server_name your domain_name or IP;
}
We must also add the location / block, we will include the proxy_params
file that specifies some general proxy parameters that need to be configured. Then we will pass the requests to the socket that we define using the proxy_pass directive:
so this would be our final result:
server {
listen 80;
server_name server_domain_or_IP;
location / {
include proxy_params;
proxy_pass http://unix:/home/ubntu/myproject.sock;
}
}
Now, to enable the Nginx server block configuration that we just created, link the file to the sites-enabled directory (create a symbolic link with ln):
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
If we have an error in our syntax, we can check with the following command if there is no error, the output will be successful.
sudo nginx -t
If this returns without indicating a problem, we can restart the Nginx process to read our new configuration:
sudo systemctl restart nginx
very good! If everything was successful you should see when you copy and paste your ip or domain in your browser url your application that returns a “HELLO FLASK”, and that would be all I hope this article has helped you to know how to deploy an application in flask with this great team of servers!
from here https://www.linkedin.com/pulse/deploying-application-flask-nginx-gunicorn-3-daniela-morales.
Thanks !