Configure Python 3, Flask and Gunicorn on Ubuntu 18.04 LTS

Post updated by Matt Makai on June 15, 2018. Originally posted on June 14, 2018.

Ubuntu Linux's latest Long Term Support (LTS) operating system version is 18.04 and was released in April 2018. The 18.04 update is code named "Bionic Beaver" and it includes Python 3 by default. However, there are bunch of dependencies you will need to install to get this release set up as a development environment.

In this tutorial we will get Python 3.6 configured with development system packages to start a new Flask web application project and run it with Green Unicorn (Gunicorn).

Our Tools

Our project will use the Ubuntu 18.04 release along with a few other libraries. Note that if you are using the older 16.04 LTS release, there is also a guide that will walk you through setting up that version as your development environment.

We will install the following tools as we step through the rest of the sections in this tutorial:

If you're running on Mac OS X or Windows, use virtualization software such as Parallels or VirtualBox with the Ubuntu .iso file. Either the amd64 or i386 version for 18.04 will work. I am using amd64 for development and testing in this tutorial.

When you boot up to the Ubuntu desktop you should see a screen like this one.

We're ready to get our development environment configured.

System Packages

Open up a terminal window to proceed with the setup.

Use the following two commands to check which version of Python 3 is installed

python3 --version
which python3

The Python version should be 3.6.5 and the location /usr/bin/python3.

Our Ubuntu installation requires a few system packages to do development rather than just run Python scripts. Run the following apt-get command and enter your sudo password to allow restricted system access.

sudo apt-get install python3-dev python3-pip python3-virtualenv

We should see the following prompt requesting sudo access. Enter y to let the system package manager complete the installation.

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  linux-headers-4.15.0-20 linux-headers-4.15.0-20-generic
  linux-image-4.15.0-20-generic linux-modules-4.15.0-20-generic
  linux-modules-extra-4.15.0-20-generic
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  dh-python libexpat1-dev libpython3-dev libpython3.6-dev python3-setuptools
  python3-wheel python3.6-dev
Suggested packages:
  python-setuptools-doc
The following NEW packages will be installed:
  dh-python libexpat1-dev libpython3-dev libpython3.6-dev python3-dev
  python3-pip python3-setuptools python3-virtualenv python3-wheel
  python3.6-dev
0 upgraded, 10 newly installed, 0 to remove and 11 not upgraded.
Need to get 3,617 kB/3,661 kB of archives.
After this operation, 20.2 MB of additional disk space will be used.
Do you want to continue? [Y/n] 

The package manager will do the dirty work and should report when the installation finishes successfully.

(...clipped a bunch of installation lines for brevity...)
Unpacking python3-wheel (0.30.0-0.2) ...
Setting up python3-wheel (0.30.0-0.2) ...
Setting up python3-virtualenv (15.1.0+ds-1.1) ...
Setting up python3-pip (9.0.1-2.3~ubuntu1) ...
Setting up libexpat1-dev:amd64 (2.2.5-3) ...
Processing triggers for man-db (2.8.3-2) ...
Setting up python3-setuptools (39.0.1-2) ...
Setting up dh-python (3.20180325ubuntu2) ...
Setting up libpython3.6-dev:amd64 (3.6.5-3) ...
Setting up python3.6-dev (3.6.5-3) ...
Setting up libpython3-dev:amd64 (3.6.5-3) ...
Setting up python3-dev (3.6.5-3) ...

The packages we need are now installed. We can continue on to install our Python-specific dependencies.

Virtual environment

We installed virtualenv and pip to handle our application dependencies. We can now use them to download and install Flask and Gunicorn.

Create a directory to store your virtualenvs. Then create a new virtualenv within that directory.

# make sure pip and setuptools are the latest version
pip3 install --upgrade pip setuptools
# the tilde ("~") specifies the user's home directory, such as "/home/matt"
cd ~
mkdir venvs
# specify the system python3 installation
python3 -m venv venvs/flask1804

Activate the virtualenv.

source ~/venvs/flask1804/bin/activate

Our prompt will change when the virutalenv is activated.

Our virtualenv is now activated with Python 3. We can install any dependencies we need such as Flask and Gunicorn.

Flask and Gunicorn

We're going to use pip within our new virtualenv but it's a good idea to update it to the latest version. We should also install the wheel package to remove installation warnings when pip tries to use Python wheels, which are the newest standard in an admittedly long line of Python distribution package models.

pip install --upgrade pip
pip install wheel

We can now install Flask and Green Unicorn via the pip command.

pip install flask gunicorn

Look for output similar to the following to ensure the libraries installed without an issue.

(flask1804) [email protected]:~$ pip install flask gunicorn
Collecting flask
  Using cached https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl
Collecting gunicorn
  Using cached https://files.pythonhosted.org/packages/55/cb/09fe80bddf30be86abfc06ccb1154f97d6c64bb87111de066a5fc9ccb937/gunicorn-19.8.1-py2.py3-none-any.whl
Collecting click>=5.1 (from flask)
  Using cached https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl
Collecting Werkzeug>=0.14 (from flask)
  Using cached https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl
Collecting itsdangerous>=0.24 (from flask)
  Using cached https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz
Collecting Jinja2>=2.10 (from flask)
  Using cached https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask)
  Using cached https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
Building wheels for collected packages: itsdangerous, MarkupSafe
  Running setup.py bdist_wheel for itsdangerous ... done
  Stored in directory: /home/matt/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
  Running setup.py bdist_wheel for MarkupSafe ... done
  Stored in directory: /home/matt/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
Successfully built itsdangerous MarkupSafe
Installing collected packages: click, Werkzeug, itsdangerous, MarkupSafe, Jinja2, flask, gunicorn
Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 gunicorn-19.8.1 itsdangerous-0.24

Create a new directory named flask1804 under your home directory (not within the venvs subdirectory) that will store our Flask test project. Change directory into the new folder.

mkdir ~/flask1804
cd ~/flask1804

Create a new file named __init__.py within our flaskproj directory so we can test to make sure Flask is working properly. I usually use Vim but Emacs and other development environments work great as well.

Within __init__.py write the following code.

from flask import Flask, Response


app = Flask(__name__)

@app.route("/")
def index():
    return Response("It works!"), 200

if __name__ == "__main__":
    app.run(debug=True)

We could run our app with the Flask development server using the python __init__.py command. Instead run the Flask app with Gunicorn. Go to the directory above the flask1804 folder, in our case we can enter cd ~ then use the gunicorn command:

gunicorn flask1804.app:app

We should see:

[2018-06-15 15:54:31 -0400] [5174] [INFO] Starting gunicorn 19.8.1
[2018-06-15 15:54:31 -0400] [5174] [INFO] Listening at: http://127.0.0.1:8000 (5174)
[2018-06-15 15:54:31 -0400] [5174] [INFO] Using worker: sync
[2018-06-15 15:54:31 -0400] [5177] [INFO] Booting worker with pid: 5177

Great now we can bring up our shell Flask app in the web browser at the localhost:8000 or 127.0.0.1:8000 address.

Now you're ready for some real Flask development!

Ready to Code

That provides a quick configuration for getting started on 18.04 LTS developing Flask applications with the Gunicorn WSGI server.

Next up you should check out the following tutorials that use this Flask configuration:

Alternatively you can also determine what to code next in your Python project by reading the Full Stack Python table of contents page.

Questions? Contact me via Twitter @fullstackpython or @mattmakai. I'm also on GitHub with the username mattmakai.

Something wrong with this post? Fork this page's source on GitHub and submit a pull request.


Sign up for a monthly email with Full Stack Python tutorials. No spam ever.

Sponsored By

Okta logo.

Secure and manage identities in your Python web apps with Okta.


Rollbar logo

Fix errors in your Python code before your users see them by monitoring with Rollbar.


Digital Ocean logo.

Easily deploy your Python web apps to Digital Ocean's reliable cloud computing platform.


Scout logo

Scout monitors the performance of your Python apps, identifying slow queries, memory bloat, and more. Free during Tech Preview.


Matt Makai 2012-2018