How to Build a Containerised Python Web Application with Docker, Flask and uWSGI
Ever wondered how to deploy a web application on your machine? It’s easier than you think. In this tutorial, we’ll build a simple web application that displays “Hello World” using Flask. Flask is a lightweight python framework used to build web applications. We’ll also look at how to build the back-end of our web application and deploy it on your machine inside a Docker container.
Dockerising, or containerising your web app using Docker, is in simple terms packaging your app and your environment so that a new user can easily set up and run your application from the get-go. There are 3 Docker-related keywords you may want to look out for in this short tutorial — a Dockerfile, a Docker image and a Docker container.
CREATING A FLASK APP
We will be using Python 3 in this tutorial. Make sure the “flask” python library is installed. You can install it using the following command:
$ python -m pip install flask
As a general rule, list all the python libraries that you install to create your project inside a file named “requirements.txt”.
Let’s start with building a simple python flask app. Create an app.py file with the following code:
from flask import Flask, render_templateapp = Flask(__name__)
We have created a flask app called ‘app’. Now let’s add our root page:
This is called a flask route. It’s the chunk of code that is executed when the ‘/’ path of your web app is accessed. Here, we are telling flask to return an HTML template named “home.html”. By default, flask looks for templates in the “templates” folder.
Create a folder inside your project directory and name it “templates”. Now let’s create the HTML template called “home.html” inside that folder:
<html> <body> <h1> Hello World! </h1> </body></html>
This is a simple HTML page that displays “Hello World!” in bold. Now that we have our template and our app, let’s see if it works!
Run the following commands on your terminal:
$ set FLASK_APP='app.py'
$ flask run -p 5000
This should run your flask app on port 5000 of your local machine at “localhost:5000/” and you can access it on your browser:
CONTAINERISING THE FLASK APP
First, install the Docker engine on your desktop from here. This should also install Docker on your CLI.
Now, let’s create a Dockerfile. A Dockerfile is used by the Docker engine to build an image of your container, similar to how you use a Windows media creation tool to build an ISO file for backing up your Windows OS.
Create a file called “Dockerfile” and copy the following into it:
#Use CentOS 7 as the container OSFROM centos:7
#Copy our files to the containerCOPY . ./app
#Install python and other programs required to run our appRUN yum install -y python-pip python36u python36u-libs python36-devel python36u-pip uwsgi which gcc#Change the working directory to /appWORKDIR /app#Changing the default python version from 2 to 3. We do this by first renaming the old python version and linking python filename to python3.6.RUN mv /usr/bin/python /usr/bin/python_oldRUN cd /usr/bin && ln -s python3.6 python#Install the required python packages listed in the requirements fileRUN python -m pip install -r requirements.txt#Run uwsgi with the configuration in the .ini fileCMD ["uwsgi","--ini","app.ini"]#Expose port 90 of the container to the outsideEXPOSE 90
You can see that in the Dockerfile we have set up the environment we need to run our app and at the end we used the “uwsgi” command to run our app inside the container.
USING uWSGI TO SERVE OUR FLASK APP
As mentioned earlier, Flask is a light python framework that allows you to build web applications compliant to python’s WSGI (Web Server Gateway Interface) conventions. These are standards set by python on how a web server should interact with a python web application like during forwarding of requests. Flask has been built using the Werkzeug library (an older python framework intended to make creating WSGI compliant web apps easier). Flask comes with Werkzeug’s development-level server, which is what we used earlier to test our flask app. Now, we can’t use this server for deploying our app, which is where uWSGI comes into the picture.
uWSGI is a web server that allows us to send HTTP requests to our web app and can be used for production-level deployment of our web app. There are other alternatives like Gunicorn. But, we will use uWSGI to serve our web app inside our Docker container as, objectively, it works better. For this, we need to ensure that we install uWSGI inside our container. Since, uWSGI is written in C we will also need “gcc” which is a C compiler for Linux. We have already done this earlier inside the Dockerfile. Now, let’s create the .ini file that will contain the configuration for uWSGI to run our app. Let’s name it “app.ini” and copy the following into it:
[uwsgi]wsgi-file = wsgi.pymaster = 5http = :90die-on-term = true
This configuration file tells uWSGI to look for a file called “wsgi.py”, which contains a chunk of python code that starts up our Flask app. The config file also tells uWSGI to serve HTTP requests on port 90 of the machine (or in this case our Docker container). Remember, we asked for port 90 of our Docker container to be exposed inside the Dockerfile. Now, let’s create “wsgi.py” and copy the following code into it:
from app import app as application
if __name__ == "__main__": application.run()
Don’t worry, we’re almost there now!
RUNNING THE DOCKER CONTAINER
We now have all the files we need to deploy our web application. So, let’s see how to put everything together and run our container:
First, start up Docker desktop and make sure it’s running. On your CLI type in the docker build command:
$ sudo docker build -t myapp:latest .
This will build a Docker image tagged “myapp:latest” from the Dockerfile we created earlier. Don’t miss the “.” at the end. Expect a wait of 1–2 mins or maybe even more depending on your internet speed. You’ll see docker executing each line of code in the Dockerfile.
By default the docker command looks for a file named “Dockerfile”. If you want it look for a different filename you can use the “ -f ” tag.
After our Docker image is built, we can run a Docker container using the image by typing in the following command:
$ sudo docker run -p 9090:90 -t myapp:latest
This command will run the docker container and map port 9090 of your machine to port 90 of the container. To run the container detached you can use the “-d” tag.
To see the running docker container type in:
$ sudo docker ps
Hurray! You have successfully deployed a containerised web application on your machine. To see it working go to “localhost:9090” on your browser.
You can refer to the code I used in my git repository here. You can now build on your web application adding more useful Flask routes and better-looking HTML pages
…. Hope this helps you start your web app development journey!