Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
– from What Is Docker?
If you are new to Docker, this guide will show you how to create a basic Docker container.
I have a small Python Flask web application that I want to put inside a Docker container. I also want to run the web application using a server called uwsgi. Dockerizing a Python Flask application will give you a straightforward intro into Docker containers.
Build a Docker Container
Contents of ./requirements.txt
This file specifies software dependencies needed for our web application.
Flask==0.10.1 itsdangerous==0.24 Jinja2==2.8 MarkupSafe==0.23 Werkzeug==0.11.5
Contents of ./app.py
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
Contents of ./Dockerfile
FROM ubuntu:14.04 # Update OS RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list RUN apt-get update RUN apt-get -y upgrade # Install Python RUN apt-get install -y python-dev python-pip # Add requirements.txt ADD requirements.txt /webapp # Install uwsgi Python web server RUN pip install uwsgi # Install app requirements RUN pip install -r requirements.txt # Create app directory ADD . /webapp # Set the default directory for our environment ENV HOME /webapp WORKDIR /webapp # Expose port 8000 for uwsgi EXPOSE 8000 ENTRYPOINT ["uwsgi", "--http", "0.0.0.0:8000", "--module", "app:app", "--processes", "1", "--threads", "8"]
In this configuration:
First, we update the Ubuntu OS that is shipped with the container:
RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list RUN apt-get update RUN apt-get -y upgrade
Next, we install Python, Python development files and a package manager for Python. Since we are using a Debian-based OS inside the container, apt-get is used to install packages. This may be different, depending on the flavor of Linux you ship:
# Install Python RUN apt-get install -y python-dev python-pip
Next, we install all dependencies needed for our app. This is donebeforeadding our application files to the container because Docker will skip this step if requirements.txt has not changed upon subsequent builds. Every Docker command builds a layer that is cached and if a single layer is changed, Docker will invalidate this cache. This ordering will prevent our dependencies from being reinstalled upon changes to our application code.
# Add requirements.txt ADD requirements.txt /webapp # Install uwsgi Python web server RUN pip install uwsgi # Install app requirements RUN pip install -r requirements.txt
Next, we add all application files to the /webapp directory inside the container:
# Create app directory ADD . /webapp
Next, we set the working directory to /webapp:
# Set the default directory for our environment ENV HOME /webapp WORKDIR /webapp
Next, port 8000 is exposed to allow communication to the container. By default, no ports are exposed:
# Expose port 8000 for uwsgi EXPOSE 8000
Finally, we specify the command to run when the container is started:
ENTRYPOINT ["uwsgi", "--http", "0.0.0.0:8000", "--module", "app:app", "--processes", "1", "--threads", "8"]
Alternatively, we can set the ENTRYPOINT to a command without flags. This will allow flags to be specified when the container is initialized:
ENTRYPOINT ["uwsgi"]
Build the Docker container:
docker build --no-cache --rm -t travcunn/flask .
Run the Container
docker run -d \ --cpuset-cpus 1 \ --name flask \ --restart=always \ travcunn/flask
In this configuration:
- -d runs the container in detached mode. To run the container in the foreground, remove this flag.
- –cpuset-cpus 1 restricts the container to use only 1 CPU. To remove this restriction, remove this flag.
- –name flask allows custom container names, where we assign the container name “flask”. If a name is not specified, Docker will automatically assign one.
- –restart=always will automatically restart the container if the application exits.
- travcunn/flask specifies the image for the container, which was built in a previous step.
Test Your Container
Once the container is running, we can check if the web server is running.
When a Docker container is started, it is automatically assigned an IP address that is accessible only to your local machine. To check our HTTP server, we need to find the IP address of the container. First, find the container ID:
> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5987b02d8c61 travcunn/flask "uwsgi --http 0.0.0.0" 7 seconds ago Up 6 seconds 8000/tcp flask
Next, inspect the container to find the IP:
> docker inspect --format '{{ .NetworkSettings.IPAddress }}' 5987b02d8c61 172.17.0.2
Now visit: http://172.17.0.2:8000 or the IP address of the container in your web browser. You should see a response from the server running inside your container.
Stay Tuned
I hope you enjoyed this article on dockerizing a python flask application. Stay tuned for future Docker posts about application service discovery, connecting Docker containers, and using databases with Docker applications.