Jenkins Project: Building CI/CD Pipeline for Scalable Web Applications

Docker

Building a Custom Docker Image

In this guide, you'll learn how to build a custom Docker image for a Flask application and push it to Docker Hub. We will containerize a simple Flask app that manages tasks and walk through creating the Dockerfile, building the image, and deploying it.

Application Overview

Our sample Flask application (app.py) manages tasks with basic operations. Below is an excerpt of the code:

from flask import Flask, render_template, request

app = Flask(__name__)

# A dictionary to store tasks with an ID
tasks = {}
task_id_counter = 1

@app.route('/', methods=['GET', 'POST'])
def index():
    global task_id_counter
    response_text = ""

    if request.method == 'POST':
        if 'add_task' in request.form:
            task_content = request.form.get('task_content')
            if task_content:
                tasks[task_id_counter] = task_content
                task_id_counter += 1

        elif 'delete_task' in request.form:
            task_id_to_delete = int(request.form.get('task_id_to_delete'))
            tasks.pop(task_id_to_delete, None)

    return render_template('index.html', tasks=tasks)

Creating the Dockerfile

To containerize the Flask application, create a Dockerfile that includes instructions for setting the base image, copying your source code, installing dependencies, exposing the necessary port, and starting the application.

Below is an example Dockerfile for our Flask app:

FROM python:3.12.0b3-alpine3.18
COPY /application
WORKDIR /application
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]

This Dockerfile performs the following actions:

  • Base Image: Uses a Python image based on Alpine Linux, tagged as version 3.12.0b3‑alpine3.18.
  • Copying Code: Transfers your application source code into the container.
  • Setting the Working Directory: Switches context to /application for subsequent commands.
  • Installing Dependencies: Copies requirements.txt and installs the necessary Python packages.
  • Exposing Port 5000: Documents the port on which the container will listen.
  • Running the Application: Executes the command to start the Flask application.

Note

The EXPOSE instruction is for documentation purposes only and does not publish the port. Use the -p flag to map container ports to the host, e.g., docker run -p 5000:5000 my-flask-app:v1.

Selecting the Appropriate Base Image

Since this application utilizes Python, we selected an Alpine-based Python image available on Docker Hub for its reduced size and efficiency. Searching for "python" on Docker Hub provides multiple options, including slim and Alpine variants.

The image shows the Docker Hub website, featuring a search bar and sections for trusted content, spotlight articles, and categories related to development and machine learning.

The image shows a search results page on Docker Hub for "python," displaying various Python-related container images with options to filter by products, trusted content, and categories.

Copying Application Files

The Dockerfile uses the COPY command to add your application files and dependency file into the image. Here’s an illustrative snippet:

FROM python:3.12.0b3-alpine3.18
COPY /application 
COPY hello.txt /absolute/path
COPY hello.txt relative/to/workdir

This demonstrates the flexibility of the COPY command, allowing files to be added either to an absolute path or relative to the current working directory. Following these commands, the Dockerfile sets up the working directory, installs dependencies, exposes the application port, and defines the startup command.

Building the Docker Image

With your Dockerfile ready, build the image by running the following command from the directory containing your Dockerfile. The -t flag tags the image:

docker build -t my-flask-app:v1 .

This command processes each instruction in the Dockerfile and generates a Docker image tagged my-flask-app:v1.

Running the Container

After building the image, you can verify it by listing all Docker images:

docker image ls

To run the container, use the following command:

docker run my-flask-app:v1

The terminal output should confirm that your Flask application is running on port 5000. Press Ctrl+C to stop the container.

Pushing the Image to Docker Hub

After creating your Docker image, the next step is to push it to a repository like Docker Hub for easy deployment and team access.

Logging in and Creating a Repository

First, log into Docker Hub using:

docker login

After entering your credentials, create a new repository on Docker Hub (for example, "jenkins-flask-app").

Retagging and Pushing the Image

Docker Hub requires images to be tagged with the format: username/repository:tag. Retag your image using your Docker Hub username:

docker image tag my-flask-app:v1 sanjeevkt720/jenkins-flask-app:v1

Verify the new tag by listing your images:

docker image ls

Now, push the image to Docker Hub:

docker push sanjeevkt720/jenkins-flask-app:v1

The terminal should display confirmation messages indicating that the image layers and digest have been successfully pushed.

Updating the Application and Creating New Versions

As your application evolves, update the code and, if necessary, adjust the Dockerfile instructions. Build a new version of the image with an updated tag. For example, after updating the application, rebuild the image as version three:

Dockerfile remains unchanged:

FROM python:3.12.0b3-alpine3.18
COPY /application
WORKDIR /application
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]

Rebuild the image:

docker build -t sanjeevkt720/jenkins-flask-app:v3 .

Confirm the new image tag:

docker image ls

Push the updated image to Docker Hub:

docker push sanjeevkt720/jenkins-flask-app:v3

A successful push will indicate that the new image version is available in your Docker Hub repository.

Additional Considerations

  • Port Mapping: To publish a container port on the host, use the -p flag with docker run (e.g., docker run -p 5000:5000 sanjeevkt720/jenkins-flask-app:v1).
  • Alternative Registries: While Docker Hub is widely used, repositories on AWS, Azure, and GCP also support similar tagging and push commands.

By following these steps, you've successfully containerized your Flask application, built custom Docker images, and deployed them to Docker Hub for streamlined delivery and collaboration.

Resources

Resource TypeUse CaseExample Command
Docker BuildBuilding a Docker image from your Dockerfiledocker build -t my-flask-app:v1 .
Docker RunRunning a container from the imagedocker run -p 5000:5000 my-flask-app:v1
Docker PushPushing your image to a repositorydocker push sanjeevkt720/jenkins-flask-app:v1

For more detailed documentation, visit these links:

Happy containerizing!

Watch Video

Watch video content

Previous
Docker Workflow