Deploying a Flask App
This page describes how to deploy a Flask app on an Azure (or other Linux) virtual machine.
Note
Before completing this, create an Azure VM and set up SSL on it.
When you're all done, your Flask app will be managed and run by the Apache web server. Apache is a production-grade web server that handles HTTPS and many other things for your Flask app. The web server built in to Flask is sufficient for development and testing, but is not well-suited to production deployments on the public Internet.
Overview
The steps you will need to perform:
- Create a virtual environment
- Clone your application's source code from GitHub
- Configure settings and directory paths
- Configure Apache to load or connect to your application
Create a Virtual Environment
Create a virtual environment on your virtual machine. This will be easiest if you use sudo
to launch a shell, rather than individual commands:
$ sudo -s [sudo] password for michael: # virtualenv -p /usr/bin/python3.4 /opt/flaskapp-venv # source /opt/flaskapp-venv/bin/activate Running virtualenv with interpreter /usr/bin/python3.4 Using base prefix '/usr' New python executable in /opt/flaskapp-venv/bin/python3.4 Also creating executable in /opt/flaskapp-venv/bin/python Installing setuptools, pip...done. (flaskapp-venv)# pip install Flask Flask-Script Flask-SQLAlchemy bcrypt
Clone application source code from GitHub
$ sudo git clone https://git.txstate.edu/cs3320/animals.git /srv/animals
Set up configuration and data paths
Create a directory, data
, that can hold your data and be written by the Apache process:
$ sudo mkdir /srv/animals/data $ sudo chown www-data /srv/animals/data
Create a settings file, /srv/animals/settings.py
, for your application:
SECRET_KEY = '<secret key here>' # Path to SQLite database (note 4 slashes) SQLALCHEMY_DATABASE_URI = 'sqlite:////srv/animals/data/animals.db'
Deploying with mod_proxy
With this method, we run the Flask application as a standalone server. Apache will forward HTTP requests and websocket connections to it.
Installing Dependencies
$ sudo -s [sudo] password for michael: # source /opt/flaskapp-venv/bin/activate (flaskapp-venv)# pip install Flask-SocketIO eventlet
Starting the Server
First, we need to create a configuration file so that systemd can start and manage our server. Create the following file as /etc/systemd/system/myapp.service
:
[Unit] Description=the web application server # we need a network After=network.target [Service] # process starts, doesn't exit unless failing Type=simple # start manage.py with virtualenv ExecStart=/opt/flaskapp-venv/bin/python3 /srv/myapp/manage.py socketserver # start in its directory WorkingDirectory=/srv/chat # run as web user User=www-data Group=www-data [Install] # start with default stuff when we enable automatic startup WantedBy=default.target
Then start the server:
# systemctl daemon-reload # systemctl start myapp.service # systemctl status myapp.service ● myapp.service - the myapp application server Loaded: loaded (/etc/systemd/system/myapp.service; disabled) Active: active (running) since Thu 2016-04-28 16:58:06 UTC; 4h 35min ago Main PID: 15826 (python3) CGroup: /system.slice/myapp.service └─15826 /opt/flaskapp-venv/bin/python3 /srv/myapp/manage.py socketserver
Make sure the service is running!
To make it start automatically when the VM boots, enable
it:
# systemctl enable myapp.service
Configuring Apache
Next, we will configure Apache to pass incoming requests on to our application server. Put the following in /etc/apache2/sites-available/myapp.conf
:
ProxyPass /socket.io/ ws://localhost:5000/socket.io/ ProxyPass / http://localhost:5000/ ProxyPassReverse / http://localhost:5000/
Then enable the site and required Apache modules, and reload Apache:
# a2ensite myapp # a2enmod proxy_http proxy_wstunnel # systemctl restart apache
Then visit your site and make sure it works!
Deploying with WSGI
Note
This method does not work with Socket.IO.
Apache and Flask communicate over a protocol called WSGI, the Web Server Gateway Interface.
More information on connecting Flask and Apache is available in the Flask mod_wsgi
documentation.
WSGI
The first thing to do is create a small WSGI bootstrap script. This can live in your Git repository, and should be named something like myapp.wsgi
. It should contain the following:
import sys, os.path sys.path.insert(0, os.path.dirname(__file__)) from myapp import app as application
Change myapp
to your application's main module (the one that pulls in the views & API files).
That's all you need for that file!
Configure Apache to load the application
Create a file /etc/apache2/sites-available/flaskapp.conf
containing the following lines:
# Use our virtual environment WSGIPythonHome /opt/flaskapp-venv # Map the application to a URL WSGIScriptAlias / /srv/animals/animals.wsgi # Allow access to animals <Directory /srv/animals> Options -Indexes Require all granted </Directory>
You can edit the file with the command
sudo nano /etc/apache2/sites-available/flaskapp.conf
Then enable the site and restart Apache:
$ sudo a2ensite flaskapp $ sudo systemctl restart apache2
The site should now be available, at e.g. https://txst-cs3320-demo.westus.cloudapp.azure.com.
Hint
If your resources, such as Pure, aren't being loaded when you visit the site over HTTPS, make sure that all your CDN resources use HTTPS instead of HTTP.
Also, Yahoo!'s CDN doesn't support HTTPS. Instead, use jsDelivr:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/pure/0.6.0/pure-min.css">
Hint
If you have problems (500, 400, etc.), look at the file /var/log/apache2/error.log
.