We have launched EaseAnnotate!

Try Out Now!
Pythonify logo
docker

Containerize your Python Application with Docker

12 min read
pythonify
Containerize your Python Application with Docker

Introduction

The world of application development has evolved significantly, thanks to containerization technologies such as Docker. This article seeks to shed light on how you can leverage Docker to containerize your Python application, creating portable and easy-to-deploy software pieces. Python, known for its simplicity and extensive libraries, is a preferred choice of language for many developers. Docker helps streamline Python app deployment by creating a uniform environment for the app, no matter where it's run. This article provides a step-by-step guide to packaging your Python application into a Docker container, setting you up for hassle-free deployment.

Python and Docker: Overview

Python in Application development

If you are a regular visitor of Pythonify then you know, Python is a high-level programming language renowned for its simplicity, readability, and wide-ranging application. Some developers label it as a "Swiss army knife" due to its flexibility and ease of learning. Python boasts an expansive standard library that supports numerous tasks including web development, data analysis, machine learning, artificial intelligence, among others.

What is Docker?

But you might not be familiar with Docker. It is an open-source platform that automates the deployment, scaling, and management of applications. Docker uses containerization, a lightweight form of virtualization, to encapsulate an application along with its environment. But what exactly are Docker containers? Imagine them as portable, self-sufficient packages that contain everything needed to run an application - the application itself, along with all dependencies, libraries, and system tools required. This encapsulation ensures that the application will run uniformly and consistently on any Linux machine, irrespective of any customized settings of the machine that might differ from those of the machine on which the app was developed.

Prerequisites

Before starting the tutorial on containerizing your Python Application with Docker, you should have the following tools and knowledge:

  1. Basic Knowledge of Python Programming: You should be familiar with Python's syntax and programming concepts. A good resource for learning Python is the Python official documentation. Online platforms like Codecademy's Python course or Coursera's Python for Everybody also offer comprehensive tutorials.

  2. Python Development Environment: Ensure you have a working Python development environment. You can download and install Python from the official Python website. Additionally, you may want to familiarize yourself with a Python Integrated Development Environment (IDE) like PyCharm or Visual Studio Code.

  3. Basic Understanding of Docker: It would be helpful to have a rudimentary understanding of Docker and its components such as Dockerfile, Docker Images, and Docker Containers. Docker’s official documentation is excellent for understanding Docker at a high level. For a deeper dive, consider the Docker for beginners course.

  4. Docker Software Installed: Docker must be installed on your computer to build and run Docker containers. You can download Docker Desktop for Windows, Mac, or follow the installation guide for Linux.

Having the above tools and knowledge will set the stage for successfully containerizing a Python application with Docker. If any of these seems unfamiliar, consider exploring the provided resources to get up to speed.

Creating a Python Application

Let's begin by creating a simple Python application. For this example, we'll develop a Flask web application.

Step 1: Set Up your Python Environment

Make sure to install Python and set up a virtual environment (venv), which keeps dependencies required by different Python applications separate.

Here are the commands to do so:

bash
$ python3 -m venv venv $ source venv/bin/activate

Step 2: Install Necessary Python Packages

For our Flask application, we need to install Flask. You can do this using pip, the Python package installer:

bash
$ pip install flask

Step 3: Create the Flask Application

Now, write a simple Flask application. Create a new file, app.py, and write the following code:

python
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)

This simple web application creates a route (/) that returns 'Hello, World!' when a GET request is processed.

Step 4: Test the Application Locally

Run your application locally by using the following command:

bash
$ python app.py

In your web browser, navigate to http://localhost:5000 to see your application in action. You should see the text "Hello, World!"

With your Python application functioning as expected, you're ready for the next step: preparing this application for Docker by creating a Dockerfile.

Essential Components of a Python Application

While Python applications can vary greatly depending on their purposes, some components are commonly present:

  1. Source Code: The Python script files which make up the application. In the simplest cases, it might be a single .py file, but for larger applications, the source code will be organized into multiple modules or packages.

  2. Dependencies: The external Python packages that your application relies on to function. These are typically specified in a requirements.txt file and installed using pip.

  3. Environment: The versions of Python and other tools your application needs to run correctly. These can often be captured in a file like runtime.txt.

  4. Application Entry Point: The part of your code where execution begins. For a script, it's typically main function (if __name__ == '__main__'). For a web application, it might be the point where you instantiate your application server and start listening for requests.

Remember, an ideal Python application is one that's well-structured and includes a clear division of responsibilities among components, allowing for easier troubleshooting, testing, and maintenance.

Writing a Dockerfile

Introduction to Dockerfile

A Dockerfile is the blueprint of a Docker image. It's a text file that contains all the commands, in order, needed to build a given image. The Dockerfile reference can automate the build process, making it more efficient and less prone to human error than manual configuration.

A Dockerfile essentially includes the following steps:

  • Specifies a base image
  • Defines what additional dependencies to install
  • Specifies any environment variables
  • Defines what application to run on container startup

Creating a Dockerfile for the Python Application

The process for creating a Dockerfile for our Python Flask application involves the following steps:

Base Image

The first line of the Dockerfile defines our base image. We will use a lightweight Python image. Add a Dockerfile to your project and open it in a text editor:

Dockerfile
# Use an official Python runtime as a parent image FROM python:3.8-slim-buster

Dependencies Installation

Next, we'll add the additional libraries that our Python app requires. Docker runs each command in the Dockerfile in order, layering the results.

Dockerfile
# Set the working directory in the container to /app WORKDIR /app # Copy the current directory contents into the container at /app COPY . /app # Install any needed packages specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt

Be sure to create a requirements.txt file in your directory and list Flask there. Docker will use pip to install these packages.

Copying Application

Next, let's copy our application code to the Docker image.

Dockerfile
# Copy the current directory contents into the container at /app COPY . /app

Exposing Ports

With our application copied onto the image, we'll need to specify which port it should use. This lets Docker route traffic to the correct port in the container:

Dockerfile
# Make port 5000 available to the world outside this container EXPOSE 5000

Default Command

Finally, we'll add the command that kicks off our application. Here, we'll use the command to start our Flask server:

Dockerfile
# Run the command to start uWSGI CMD ["uwsgi", "app.ini"]

Make sure you have a uwsgi server setup and a corresponding app.ini configuration file. If you don't have one, you can simply run the application file:

Do not use the Flask development server in production.

Dockerfile
# Run app.py when the container launches CMD ["python", "app.py"]

Here is the complete Dockerfile that we have built for our Python Flask application:

Dockerfile
# Use an official Python runtime as a parent image FROM python:3.8-slim-buster # Set the working directory in the container to /app WORKDIR /app # Copy the current directory contents into the container at /app COPY . /app # Install any needed packages specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt # Make port 5000 available to the world outside this container EXPOSE 5000 # Run app.py when the container launches CMD ["python", "app.py"]

Make sure to replace the file names and port numbers as per your application's requirements. This Dockerfile can be used as a starting point to most web MVC applications, but it needs to be tweaked to suit your specific requirements. Any change in the application's dependency files or a need for specific runtime environment will require you to modify the Dockerfile.

Building Docker Image

Docker Image

A Docker image is a read-only template that contains a snapshot of a live container. It is created from a list of instructions located in the Dockerfile. The image includes parts needed to run an application, such as the application itself, dependencies, libraries, binaries, and other runtime requirements. Docker images are portable and can be shared, stored, and updated. Images are used to create Docker containers.

Building Docker Image from Dockerfile

  1. Ensure you have a Dockerfile: The first step to building a Docker image is to ensure that you've written your Dockerfile with the appropriate instructions to set up your application. This should be located in the root directory of your application.

  2. Check Dockerfile Syntax: Make sure there are no syntax errors in your Dockerfile. The Docker build process interprets every command in the Dockerfile and executes them in order.

  3. Build the Docker Image: Open the terminal in your application's root directory (where your Dockerfile exists), and build your Docker image using the following command:

bash
$ docker build -t <YOUR_IMAGE_NAME> .

Replace <YOUR_IMAGE_NAME> with a name for your Docker image. The -t option is used to tag the image with a memorable name, and the . refers to the current location (i.e., the Dockerfile location).

  1. Verify the Docker Image: After building your image, you can verify it by using the following command to list out all the Docker images:
bash
$ docker images

In the command output, you should see your Docker image listed.

  1. Updating the Docker Image: If you make changes to your Dockerfile after the image is created, you can update the image by running the build command again. Docker utilizes layer caching, which means if you only changed a part of your Dockerfile, only the layers from that part forward will be rebuilt - making the process faster.

Upon successful completion of these steps, you would have built a Docker image from a Dockerfile. This image is a lightweight, standalone, and executable software package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and config files.

Running and Testing the Docker Container

Docker Container and Execution

A Docker container is a runtime instance of a Docker image. It packages up the application's code, configurations, and dependencies so that the application runs in any environment. Essentially, it's a process in isolated user-space on the host operating system that runs your application.

After successfully building a Docker image of your Flask application, you can then initiate it as a Docker container. Run the following command:

bash
$ docker run -d -p 4000:5000 <YOUR_IMAGE_NAME>

The -p flag redirects a public port to a private port in the container. <YOUR_IMAGE_NAME> is the name of the Docker image we built. Running this command returns a container ID.

After starting the container, your application is accessible from http://localhost:4000 in your preferred web browser.

Testing and Troubleshooting the Application

To ensure your application runs as expected, navigate to http://localhost:4000 in your web browser. You should be greeted with "Hello, World!", confirming that your application is running successfully.

If the application isn't functioning as expected, you can use the $ docker logs <container_id> command to fetch the logs of the container. This will display any error messages which can help in debugging.

bash
$ docker logs <CONTAINER_ID>

Here, replace <CONTAINER_ID> with your Docker container ID obtained from the docker run command.

In Docker, testing and troubleshooting are vastly simplified as everything is self-contained. Any problems can be systematically isolated and rectified, ensuring your application runs smoothly in different environments.

This streamlined process of containerizing Python applications with Docker highlights the compatibility and robustness provided by leveraging Docker containerization.

Conclusion

Containerization has fundamentally revolutionized modern application development and deployment patterns, and its implementation using Docker has become an industry standard. Docker, combined with Python's flexibility and ease of use, offers an impressive set of tools to streamline application development and boost consistency across all stages of the application lifecycle. The elegant simplicity of Docker allows developers to have enhanced control, independence, and flexibility when building applications.

In this tutorial, we have walked through the process of crafting a simple Python application, penning a Dockerfile, building a Docker image using that Dockerfile, initiating a Docker container from that image, and testing the application within the container. Each of these steps showcases Docker's ability to simplify and fortify the application deployment process, making it a must-have skill for modern developers.

Remember, the process delineated in this article is a basic introduction to containerizing Python applications with Docker. It provides you with a stepping stone, but stepping into the vast world of Docker techniques and strategies offers much more. We encourage you to explore more about Docker's command-line interface, its integration with various continuous integration/continuous deployment (CI/CD) services, and more complex multi-container setups using Docker Compose or Kubernetes.

For more information refer to these,

With that, keep your codes clean and your coffees strong. Happy coding!

More Reads

Python for javascript programmers
Python

Python for javascript programmers

December 18, 2023