Containerize a Python Web Server with Docker

Why Use Containers?

When I was first learning software engineering, one of the most frustrating barriers to learning was setting up local and production environments to run my applications.

I wanted to follow industry best practices, but configuring a local postgres or a daemonizing nginx server on a digital ocean droplet ate up a lot of time that I wanted to spend building projects or working on tutorials.

Learning to run applications in containers has transformed the way I work as a software engineer. It allows me to easily package and run nearly anything I want in a consistent way across local and production environments.

Moving from local development to production is as simple as building my Dockerfile, pushing the image up to a registry, and telling my container orchestrator to run it.

If these words don’t mean anything to you right now that’s ok. We’ll cover container registries and orchestration soon enough.

For now, let’s start by exploring an example of how to containerize and run a python web server.

Configure Filesystem

pwd and highlight project directory

mkdir containerize-python-server
cd !$
mkdir src

Within your project directory, create a src directory for our application code.

Create Server

create simple_server.py
In the src directory, create a file called simple_server.py. This file will run our simple http server:

from http.server import HTTPServer, SimpleHTTPRequestHandler

We will use an HTTPServer class and request handler from the python standard library to keep things as simple as possible.

def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
    """Entrypoint for python server"""
    server_address = ("0.0.0.0", 8000)
    httpd = server_class(server_address, handler_class)
    print("launching server...")
    httpd.serve_forever()

Define a function called run that instantiates and runs an instance of HTTPServer. Notice the server_address argument tells our HTTPServer instance to listen on port 8000 of our local machine.

if __name__ == "__main__":
    run()

We will execute our run function whenever this python module is invoked.

Validate Server Functionality

python3 src/simple_server.py

We can run the server on our local machine by executing it as a python file.

from a new terminal

curl -iv localhost:8000

Validate the server is running by opening a new tab and curling port 8000 to confirm you get a response.

Looks good!

We know that it works, so let’s kill the server by hitting ctrl-c.

Create Dockerfile

create Dockerfile
Now let’s add a Dockerfile to define the container image we will use to run our web server:

FROM python:3.8

Use an image with Python 3.8 pre-installed as our base. This will give us a python 3.8 interpreter in the container.

ENV SRC_DIR /usr/bin/src/webapp/src

COPY src/* ${SRC_DIR}/

WORKDIR ${SRC_DIR}

Copy the files in our project directory’s src folder into the container at /usr/bin/src/webapp/src. Then set the image’s working directory to the src directory.

ENV PYTHONUNBUFFERED=1

Set PYTHONUNBUFFERED=1 as an environment variable so that python sends print and log statements directly to stdout. If we did not set this, we would not see logs from our container because they would be sent to a buffer.

CMD ["python", "simple_server.py"]

Finally, use the CMD directive to tell the container a default command to execute when we run it. In this case, we execute our simple_server.py script.

Build Image

docker build . -t simple_server

Build the image and tag it as simple_server with the -t flag.

Run Image

docker run -p 8000:8000 simple_server

Run the image and forward port 8000 on your local machine to port 8000 in the docker container with the -p flag.

Validate Server Functionality

from a different terminal

curl -iv localhost:8000

Validate your containerized server is running with a curl command just like before.

And you’re done! You’ve containerized a python server.

You can kill the dockerized process by hitting ctrl-c .

In my next videos I will show you how to run a django application entirely with containers.

Leave a Reply

Your email address will not be published. Required fields are marked *