How to deploy a Flask app to your server

It is rarely briefly documented how to deploy a Flask server to a Ubuntu server on your VPS (e.g from DigitalOcean or other droplet providers)

In general, if you are about to deploy a Flask app, you may have already heard about Gunicorn and Nginx.

I suppose you are already familiar with Nginx. Let's go make the Flask app as a service.

Note: These settings are based on my RESTful api server. If your flask app contains frontend as well, the nginx config file might differ

Gunicorn

It's pretty straightforward:

  • Test if flask app can run on your server
  • Make gunicorn to serve the app as a service

1.Test if flask app can run on your server

  • make sure in your app, the requirements.txt file already contains gunicorn;
  • upload the app folder to your deployment server
  • go inside the folder, make a virtual environment using virtualenv venv
  • activate your virtual environment: source venv/bin/activate
  • install python packages in the virtual environment: pip install -r requirements.txt
  • try to serve the app: flask run
  • if everything goes fine, then you are almost done! You can now terminate the above process Ctrl + C

2. Make gunicorn to serve the app as a service

The problem of the above is when you close your terminal, the process will be terminated. To make the app run properly and robustly on your server, you'd have to make it running as a service.

Start by creating and opening a systemd socket file for Gunicorn:

sudo nano /etc/systemd/system/server.socket

Add the following code to the file:

[Unit]
Description=Gunicorn instance to server
After=network.target
[Service]
User=yourusername
Group=www-data
WorkingDirectory=/var/www/server #your directory
Environment="PATH=/var/www/server/venv/bin" #your virtual environment
ExecStart=/var/www/server/venv/bin/gunicorn --workers 4 --bind localhost:5000 app:app --timeout 1200 #the command of running gunicorn
[Install]
WantedBy=multi-user.target

We can now start and enable the Gunicorn socket.

sudo systemctl start server.socket
sudo systemctl enable server.socket

Check the status of the process to find out whether it started successfully:

sudo systemctl status server.socket

Now, your server is running on port 5000. Next, you'll wire it to a proper domain, to be accessed from outside.

Nginx

The nginx helps to setup a domain for the app. If you don't know how to use nginx yet. See this post

To do this we simply add a config file in the /etc/nginx/sites-available:

sudo nano /etc/nginx/sites-available/flaskapp
server {
server_name www.example.com; # your flask app domain here
access_log /var/log/nginx/server.log;
location / {
proxy_pass http://localhost:5000; #this port has to be the same as Gunicorn port
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 600;
}
}

And then enable the file by creating a link from it to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/flaskapp /etc/nginx/sites-enabled/

Test for syntax errors:

sudo nginx -t

Restart Nginx to enable your changes:

sudo systemctl restart nginx