Lab 11 — Docker programming
Slides. How to use Docker to containerize applications.
Example with containerizing a Flask web app
Flask is a web application framework for Python. It allows you to write very simple web applications with few lines of code. Here I include an example of a basic Flask web app and the steps to create a Docker image with it.
Writing and running the web app
Starting in a new directory, in the source code file hello.py we write:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "<html><body>Hello, world!</body></html>"
To actually run this, we will need to install Flask, which we can do by creating a Python
virtual environment, switching to it, and installing Flask using pip:
python3 -m venv .env source .env/bin/activate python3 -m pip install flask
This will add Flask to our virtual environment without adding it globally. From there, we need to tell Flask what to run by setting an environment variable:
export FLASK_APP=hello
Finally we should be able to get our web app to run by typing:
flask run --host 127.0.0.1 --port 8000
Which should show
* Serving Flask app 'hello' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8000 Press CTRL+C to quit
And if you navigate to that URL, you should see a page with the text "Hello, world!".
Containerizing our web app
Even creating a simple web application can involve a nontrivial amount of dependency management
(installing Flask) and configuration management (setting the environment variable FLASK_APP).
For a larger application, you can imagine how many more steps there could be to set it up.
Docker allows us to specify all of the steps we just did manually, together with a desired
operating system all together as an image. From images, Docker creates containers,
lightweight virtual machines running only our code and an operating system. This simplifies
deployment to servers greatly because we can create an image for our application and then
spawn containers on a server somewhere as we need, and all dependencies and configuration
steps will be automatically done for us.
To create a Docker image from our web app, we create a file named Dockerfile and in it specify a base image, copy files into it, install any dependencies/set configuration variables, and lastly give a command to run our application.
FROM python:3.13-alpine3.21 RUN python3 -m pip install flask WORKDIR /app COPY hello.py . ENV FLASK_APP=hello EXPOSE 80 CMD ["flask", "run", "--host", "0.0.0.0", "--port", "80"]
The first line specifies the base image to use for our container. This is a a
distribution of Linux with Python 3.13 already set up for us. Next we install Flask with pip like before, but without needing to create a virtual environment first.
After that, we create a folder called app in the root directory of our image. Docker will automatically move to that directory after creating it. Then we copy the source for our application, hello.py into the current directory in the image. COPY takes as arguments files on our machine, and then the last argument is a location in the image to copy to. The period . is shorthand for "current directory". The next lines set the environment variable we set before, and expose port 80 which is the port through which HTTP traffic flows.
The last line with CMD will execute our Flask application when the image is instantiated in a container. Commands given after RUN are ran when we are creating the image. In this case, we want this command to be run only when we start our container, so we use the CMD keyword instead.
Now we can use this script to build our image. Run:
docker build -t hello-world-flask.
This will have Docker build an image named hello-world-flask using the files in our current directory. After Docker builds the image, we are able to see it in Docker Desktop under the Images tab. Next, to actually create a container and run our app, type:
docker run -p 8000:80 hello-world-flask
This will create a container from our image named hello-world-flask which is actually running our code. You should see the same output as you did from running flask locally, and if you navigate to the URL you should see the same "Hello, world!" text. The 8000:80 maps the external port 8000 to the internal port 80 in the container. This way we aren't exposing port 80 on our own machine to the outside world while testing the container.