cft

Containerizing Python Web Application

Let’s start building something awesome.


user

Srinaveen Desu

3 years ago | 5 min read

In this article, we will try to build a ‘hello world’ web application and containerize the web application using docker. Why containerize? I am pretty sure there would be hundreds of articles explaining the why part in detail, but let me also give a few lines on the same.

They allow us to build a software application that can be run independently of the computing environment. Thus allowing us to concentrate more on the software and less on the underlying infrastructure.

The container can be thought like a box that has the software solution, its dependencies, and libraries, binaries, and the corresponding configuration files which can be run as a single unit.

This is containerization in a nutshell, but you could browse through the web to understand the underlying essence of it in detail. In this article, we would learn to build a basic container and deploy our ‘Hello world’ python app on the container.

Before you go any further, make sure you install docker and Python3.

Let’s start building something awesome.

Start by creating a directory, sub-directories, and files similar to below structure

$ mkdir learner_project$ mkdir learner_project/app$ touch learner_project/app/app.py$ touch learner_project/app/requirements.txt$ touch Dockerfile|-- Dockerfile
|-- app
| |-- app.py
| |-- requirements.txt
|-- static
`-- templates

The folder structure I have here is a typical python flask application structure. You could have it any way you like, but I like to keep things organized as per standards. You could ignore the directories static and templates for now.

I think with this you have set up a blueprint for your application and all you need now is to build the solution. Please note that we would not be writing more code in this article. The goal is to learn to containerize our application.

The contents of app.py look the following:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
return 'Hello World! How are you doing?'


if __name__ == '__main__':
app.run(host='0.0.0.0', port=8008, debug=True)

The contents of the file requirements.txt are :

flask

That’s it and you are ready to run your python web application. When I run the application I see the following(I installed the flask library prior to execution):

$ python app/app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:8008/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 961-117-870

What does this mean? Your web application is running and listening on localhost:8008 . When you hit the URL in the browser you should see the following message

Hello World! How are you doing?

If you have come so far that means you can pat your back. You have built your web application. So far we were building the application on our machine and all the application modules exist in our machine only. Now, if anyone wants to run this application you would have to give all the steps that you had done so far, in order for them to successfully execute the app.

Instead when we containerize our application we would be able to just give the container image and anyone could run a container from this image with a simple command and voila the application would be running as it were on our machine.

For this, we would have to define the Dockerfile which would be having a list of instructions to build an image from which a container could be brought up and then the application can be run on anyone's machine using this image.

FROM python:3.8-alpine

MAINTAINER Srinaveen Desu

COPY ./app/requirements.txt /app/requirements.txt

WORKDIR /app

RUN apk add --update \
&& pip install --upgrade pip \
&& pip install -r requirements.txt \
&& rm -rf /var/cache/apk/*

COPY ./app /app

CMD python app.py

The instruction FROM tells the image on which our application would be running and in this case, it is python followed by version tag 3.8-alpine.

The instruction MAINTAINER (optional) tells who is currently moderating this Dockerfile.

The instruction COPY tells the file that needs to be copied from your local machine to the Docker container. (source to destination)

The instruction RUN executes the commands which are responsible for setting up the required environment for our application to run and these get added into the image we would be building.

The instruction CMD is a command which is run once our container starts. A typical use case would be starting the web application server.

Now that our Dockerfile is ready, we are ready to build the image and run the container. The command is run in the directory where Dockerfile exists. It builds the image flask-demo-container which is versioned 1.0

$ pwd
/Users/desu/learner_project$ docker build --tag flask-demo-container:1.0 .Sending build context to Docker daemon 9.047MBStep 1/7 : FROM python:3.8-alpine---> 44fceb565b2aStep 2/7 : MAINTAINER Srinaveen Desu---> Using cache---> 81c543f544caStep 3/7 : COPY ./app/requirements.txt /app/requirements.txt---> Using cache---> 7446b6ed7a69Step 4/7 : WORKDIR /app---> Using cache---> 76a94dbf8407Step 5/7 : RUN apk add --update && pip install --upgrade pip && pip install -r requirements.txt && rm -rf /var/cache/apk/*---> Using cache---> bda14c8083c5Step 6/7 : COPY ./app /app---> a5f384727c69Step 7/7 : CMD python app.py---> Running in dc00695397f9Removing intermediate container dc00695397f9---> 853572c38b75Successfully built 853572c38b75Successfully tagged flask-demo-container:1.0

If you see the two successful messages you are good to go to the next step which is running the container.

$ docker run --publish 8000:8008 --name flask-demo-app flask-demo-container:1.0* Serving Flask app "app" (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: on* Running on http://0.0.0.0:8008/ (Press CTRL+C to quit)* Restarting with stat* Debugger is active!* Debugger PIN: 185-072-509172.17.0.1 - - [01/Sep/2020 06:03:47] "GET / HTTP/1.1" 200 -

If we hit the URL localhost:8000 you would see the hello world message you had seen earlier.

--publish forwards traffic hit at the port 8000of the local machine to the port 8008 of the container.

--name is the unique name that you give to the container.

And the last part of the command is the image followed by the version that we want the container to be run from.

If we want to run the container in the detached mode(running the container in the background) you would have to use the following command:

$ docker run --detach -p 8004:8008 --name flask-demo-app flask-demo-container:1.1

Note1: I have changed the image version to 1.1

Note2: In case you want to stop the container (in the case of detached mode) you would have to run the following command

docker stop <container-name>

In case you want to run the container again, you would have to remove the container before issuing the run command given above.

docker rm <container-name>

That was all for this article. Hope you had some fun learning cool stuff :).

References: Docker Doc

Upvote


user
Created by

Srinaveen Desu

A pythonista by nature. I like learning new technologies and building innovative solutions out of it.


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles