Writing Dockerfiles for Python application
Tags: docker, dockerfile, python, codenewbie
Published: 2021-06-16 15:21:45

*Note: The original code is from Udacity's Cloud Native Fundamentals Nanodegree Scholarship Program. The referenced files can be found [here](https://github.com/udacity/nd064_course_1).*

*This post does not provide instructions on installing Docker. For assistance, please refer [here](https://docs.docker.com/get-docker/).*

In this post we're going to go through the process of running a simple Python web app on a container. But, what is a container?

### Containers

> A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. (Source: [Docker](https://www.docker.com/resources/what-container))

As containers run on the same operating system, they require fewer resources than virtual machines. (Source: [Wikipedia](https://en.wikipedia.org/wiki/Docker_(software)))


### Python application

Let's start with a simple Python web application that serves a single endpoint. We save this file as `app.py`.
```python
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World"

if __name__ == "__main__":
    app.run(host='0.0.0.0')
```
On running the command `python3 app.py`, we can open our browser and on checking `http://0.0.0.0:5000/` (or `http://localhost:5000/`), we get a simple web page with the text "Hello World"!! 

(We use port 5000, as it is the default port for Flask. For more about getting started with Flask, please see [here](https://flask.palletsprojects.com/en/2.0.x/quickstart/).)

Since we're importing the Flask package, we need a file that contains the requirements for the app to run.
Create a new file named `requirements.txt` with the contents
```
Flask==1.1.1
```
where 1.1.1 is the Flask version. Feel free to use a different version! We'll use this file later for our Dockerfile.

Now that we have a working application, we can get started on containerizing it!

### Building an image

>  A container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings. (Source: [Docker](https://www.docker.com/resources/what-container))

To build an image, we require a Dockerfile, which is a text-based script of instructions (Source: [Docker Docs](https://docs.docker.com/get-started/02_our_app/)).

To start with, our Dockerfile requires a **parent image** on top of which our instructions will run (more info [here](https://docs.docker.com/develop/develop-images/baseimages/)).

```Dockerfile
FROM python:3.8-alpine3.12
```
Here, `python` is the image name, while `3.8-alpine3.12` is the tag. An image can have various tags, representing different versions of the image. Alpine images are smaller in size than normal images.

An optional step is to add a label to the image.
```Dockerfile
FROM python:3.8-alpine3.12
LABEL developer="importhuman"
```

Next, we need to copy the contents from our local directory to the container directory.
```Dockerfile
FROM python:3.8-alpine3.12
LABEL developer="importhuman"
COPY . /app
```
This copies all contents from the current directory, to a new directory named `/app` on the container.

Next, we set this directory as our working directory. All further instructions will be carried out in this directory.
```Dockerfile
FROM python:3.8-alpine3.12
LABEL developer="importhuman"
COPY . /app
WORKDIR /app
```

The container needs to install dependencies to run the application successfully. So, we add a command to carry out the installation.
```Dockerfile
FROM python:3.8-alpine3.12
LABEL developer="importhuman"
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
```

All these steps will build the image. To run the image and hence the container, we add the final step.
```Dockerfile
FROM python:3.8-alpine3.12
LABEL developer="importhuman"
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python3", "app.py"]
```

Our instructions are ready. Now, we can build our image!
In the command line, run the following command:
```
docker build -t image-name path/to/image
```
`-t image-name` gives your image the name "image-name", thus you can give it whatever name you'd like!
`path/to/image` is the path to the directory containing the Dockerfile. If you're running the command in the same directory as the Dockerfile, replace `path/to/image` with a dot.

Now, you can run `docker images` and you should be able to see your newly built image!