English

Containerize a Python application

Prerequisites

  • Ensure you have the latest Docker Desktop installed.
  • Have a git client installed (command-line based in the examples).

Overview

This guide will help you containerize and run a Python application using Docker.

Step 1: Get the Sample Application

The example uses the Flask framework. To start, clone the sample application repository using the following command in your terminal:

git clone https://github.com/docker/python-docker

Step 2: Initialize Docker Assets

Now that you have the application, use the docker init command inside the python-docker directory. Follow the prompts and provide the necessary information:

cd python-docker
docker init

Answer the prompts like this:

  • Application platform: Python
  • Python version: 3.11.4
  • Port for your app to listen on: 5000
  • Command to run your app: python3 -m flask run --host=0.0.0.0

After this, your directory should contain the following files: python-docker/ ├── app.py ├── requirements.txt ├── .dockerignore ├── compose.yaml ├── Dockerfile ├── README.Docker.md └── README.md

Learn more about these files by exploring the Docker-related files:

  • Dockerfile
  • .dockerignore
  • compose.yaml

Step 3: Run the Application

In the python-docker directory, run the following command in the terminal:

docker compose up --build

Open a browser and view the application at http://localhost:5000. You should see a simple Flask application. To stop the application, press ctrl+c in the terminal.

Step 4: Run the Application in the Background

To run the application detached from the terminal, add the -d option:

docker compose up --build -d

Open a browser and view the application at http://localhost:5000. To stop the application, run the following command:

docker compose down

Explore more Compose commands in the Compose CLI reference.

By following these steps, you have successfully containerized and run a Python application using Docker.

Using Containers for Python Development

Prerequisites

Make sure you've completed the "Containerize a Python Application" guide.

Overview

In this section, we'll delve into setting up a development environment for your containerized application. This involves:

  • Adding a local database and persisting data.
  • Configuring Compose to automatically update running services as you edit and save your code.

Step 1: Get the Sample Application

Clone a new repository to obtain a sample application with database connectivity logic:

git clone https://github.com/docker/python-docker-dev

In the cloned repository's directory, run docker init to generate necessary Docker files:

cd python-docker-dev
docker init

Follow the prompts:

  • Application platform: Python
  • Python version: 3.11.4
  • Port for your app to listen on: 5000
  • Command to run your app: python3 -m flask run --host=0.0.0.0

Step 2: Add a Local Database and Persist Data

Utilize containers to set up local services, such as a database. Update the compose.yaml file to define a database service and a volume for data persistence.

Open the compose.yaml file in an IDE or text editor. Uncomment all the database instructions and add the database password as an environment variable to the server service.

# Updated compose.yaml file
services:
  server:
    # ... (existing configurations)
    environment:
      - POSTGRES_PASSWORD=mysecretpassword
    # ... (existing configurations)

  db:
    image: postgres
    restart: always
    user: postgres
    # ... (existing configurations)
    environment:
      - POSTGRES_DB=example
      - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
    # ... (existing configurations)
# ... (volumes and secrets configurations)

Create a password.txt file in the db directory with the database password:

mkdir db
echo "mysecretpassword" > db/password.txt

Step 3: Run the Application

Execute the following command to start your application:

docker compose up --build

Test your API endpoint:

curl http://localhost:5000/initdb
curl http://localhost:5000/widgets

You should receive an empty response as the database is currently empty. Stop the application with ctrl+c.

Step 4: Automatically Update Services

Use Compose Watch to auto-update running services as you edit and save your code. Open your compose.yaml file and add the Compose Watch instructions:

# Updated compose.yaml file with Compose Watch
services:
  server:
    # ... (existing configurations)
    develop:
      watch:
        - action: rebuild
          path: .

  db:
    # ... (existing configurations)
# ... (volumes and secrets configurations)

Run the following command to utilize Compose Watch:

docker compose watch

In a terminal, curl the application:

curl http://localhost:5000

Changes to source files are immediately reflected in the running container. Open python-docker-dev/app.py and update the text. For example, change:

return 'Hello, Docker!'

to:

return 'Hello, Docker!!!'

Save the changes and wait for the application to rebuild. Curl the application again to see the updated text:

curl http://localhost:5000

You should now see "Hello, Docker!!!" in the response. Press ctrl+c to stop your application.


Configuring CI/CD for Your Python Application

Prerequisites

Ensure you have completed all the previous sections of this guide, starting with "Containerize a Python Application." You must also have a GitHub account and a Docker account to proceed.

Overview

In this section, you'll learn how to set up and use GitHub Actions to build, test, and push your Docker image to Docker Hub. The following steps will be covered:

  1. Create a new repository on GitHub.
  2. Define the GitHub Actions workflow.
  3. Run the workflow.

Step One: Create the Repository

1. Create a new repository on GitHub:

  • Open GitHub and create a new repository.

2. Configure Docker Hub secrets:

  • Open the repository Settings and navigate to Secrets and variables > Actions.
  • Create a new secret named DOCKER_USERNAME with your Docker ID as the value.
  • Create a new Personal Access Token (PAT) for Docker Hub (e.g., python-docker) and add it as a secret named DOCKERHUB_TOKEN in your GitHub repository.

3. Push your source code:

  • In your local repository, change the origin to the newly created repository:
    git remote set-url origin https://github.com/your-username/your-repository.git
    
  • Stage, commit, and push your local repository to GitHub:
    git add -A
    git commit -m "my commit"
    git push -u origin main
    

Step Two: Set Up the Workflow

1. Set up GitHub Actions workflow:

  • Go to your repository on GitHub and select the Actions tab.
  • Choose "set up a workflow yourself" to create a new GitHub Actions workflow file (usually under .github/workflows/main.yml).

2. Copy and paste the following YAML configuration into the editor:

name: ci

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:latest

For more information about the YAML syntax used here, see Workflow syntax for GitHub Actions.

Step Three: Run the Workflow

1. Save the workflow file and run the job:

  • Commit changes and push them to the main branch.
  • After pushing the commit, the workflow starts automatically.

2. Check the progress:

  • Go to the Actions tab on GitHub to view the running workflow.
  • Once the workflow is complete, check your repositories on Docker Hub.

3. Verify the image push:

  • If you see the new repository on Docker Hub, it indicates that GitHub Actions successfully pushed the image to Docker Hub.

Testing Your Python Deployment

Prerequisites

Make sure you've completed all the previous sections of this guide, starting with "Containerize a Python Application." Additionally, ensure that Kubernetes is turned on in Docker Desktop.

Overview

In this section, you'll use Docker Desktop to deploy your application to a fully-featured Kubernetes environment on your development machine. This enables you to test and debug your workloads on Kubernetes locally before deploying them.

Create a Kubernetes YAML File

In your python-docker-dev directory, create a file named docker-python-kubernetes.yaml. Open the file in an IDE or text editor and add the following contents. Replace DOCKER_USERNAME/REPO_NAME with your Docker username and the name of the repository created in "Configure CI/CD for your Python application."

apiVersion: apps/v1
kind: Deployment
metadata:
  name: docker-python-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      service: flask
  template:
    metadata:
      labels:
        service: flask
    spec:
      containers:
        - name: flask-service
          image: DOCKER_USERNAME/REPO_NAME
          imagePullPolicy: Always
          env:
            - name: POSTGRES_PASSWORD
              value: mysecretpassword
---
apiVersion: v1
kind: Service
metadata:
  name: service-entrypoint
  namespace: default
spec:
  type: NodePort
  selector:
    service: flask
  ports:
    - port: 5000
      targetPort: 5000
      nodePort: 30001

In this Kubernetes YAML file, there are two objects, separated by ---:

  1. A Deployment, describing a scalable group of identical pods. In this case, there's just one replica, or copy of your pod. The pod is created from the image built by GitHub Actions in "Configure CI/CD for your Python application."

  2. A NodePort service, routing traffic from port 30001 on your host to port 5000 inside the pods it routes to, allowing you to reach your app from the network.

To learn more about Kubernetes objects, refer to the Kubernetes documentation.

Deploy and Check Your Application

In a terminal, navigate to python-docker-dev and deploy your application to Kubernetes.

kubectl apply -f docker-python-kubernetes.yaml

You should see output indicating that your Kubernetes objects were created successfully.

deployment.apps/docker-python-demo created
service/service-entrypoint created

Ensure everything worked by listing your deployments.

kubectl get deployments

Your deployment should be listed as follows:

NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
docker-python-demo   1/1     1            1           15s

This indicates that one of the pods you specified in your YAML is up and running. Perform the same check for your services.

kubectl get services

You should get output like the following.

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes           ClusterIP   10.96.0.1       <none>        443/TCP          23h
service-entrypoint   NodePort    10.99.128.230   <none>        5000:30001/TCP   75s

In addition to the default Kubernetes service, you can see your service-entrypoint service, accepting traffic on port 30001/TCP.

In a terminal, curl the service. Note that a database was not deployed in this example.

curl http://localhost:30001/

You should receive the following response:

Hello, Docker!!!

Run the following command to tear down your application.

kubectl delete -f docker-python-kubernetes.yaml
0
0
0
0