Container Image Building and Tagging | Automation

Containerizing applications using Docker or other container tools is a critical part of modern CI/CD pipelines. Automating the process of building, tagging, and pushing container images simplifies deployment workflows, reduces human error, and ensures consistency.

This guide provides a bash script to automate the process of building and tagging container images. The script supports custom tagging, automated versioning, and pushing to container registries such as Docker Hub, AWS ECR, or GCP Container Registry.


Key Features of the Script

  1. Build container images automatically using Dockerfiles.
  2. Tag images dynamically with custom tags, including Git commit hashes or timestamps.
  3. Push images to container registries (optional).
  4. Validate inputs, check prerequisites, and log operations.
  5. Provide flexibility to support multiple environments (e.g., Docker Hub, AWS, GCP).

The Bash Script

Below is the script with detailed explanations, icons for user-friendly output, and examples for each step.

#!/bin/bash

# Automate Container Image Building and Tagging
# Author: [Your Name]
# Date: [Date]
# Version: 1.0

# Icons for visual feedback
CHECK="\u2714" # ✔
CROSS="\u274C" # ✘
INFO="\u2139"  # ℹ

# Function: Check if Docker is installed
function check_docker() {
    if ! command -v docker &> /dev/null; then
        echo -e "${CROSS} Error: Docker is not installed. Please install Docker to use this script."
        exit 1
    fi
    echo -e "${CHECK} Docker is installed."
}

# Function: Build the container image
function build_image() {
    local dockerfile=$1
    local image_name=$2
    local tag=$3

    if [[ ! -f "$dockerfile" ]]; then
        echo -e "${CROSS} Error: Dockerfile not found at $dockerfile"
        exit 1
    fi

    echo -e "${INFO} Building the Docker image: $image_name:$tag"
    docker build -f "$dockerfile" -t "$image_name:$tag" .

    if [[ $? -eq 0 ]]; then
        echo -e "${CHECK} Image built successfully: $image_name:$tag"
    else
        echo -e "${CROSS} Error: Image build failed."
        exit 1
    fi
}

# Function: Push the image to a registry
function push_image() {
    local image_name=$1
    local tag=$2

    echo -e "${INFO} Pushing the image: $image_name:$tag to the registry"
    docker push "$image_name:$tag"

    if [[ $? -eq 0 ]]; then
        echo -e "${CHECK} Image pushed successfully: $image_name:$tag"
    else
        echo -e "${CROSS} Error: Failed to push the image."
        exit 1
    fi
}

# Function: Generate a dynamic tag
function generate_tag() {
    local base_tag=$1
    local timestamp=$(date +"%Y%m%d%H%M%S")
    local git_hash=$(git rev-parse --short HEAD 2>/dev/null || echo "nogit")

    echo "${base_tag}-${timestamp}-${git_hash}"
}

# Main script starts here
echo "=== Automate Container Image Building and Tagging ==="

# Step 1: Check prerequisites
check_docker

# Step 2: Get user inputs
read -p "Enter the path to your Dockerfile (default: ./Dockerfile): " dockerfile
dockerfile=${dockerfile:-./Dockerfile}

read -p "Enter the name of the image (e.g., myapp): " image_name
if [[ -z "$image_name" ]]; then
    echo -e "${CROSS} Error: Image name cannot be empty."
    exit 1
fi

read -p "Enter the base tag for the image (e.g., v1): " base_tag
base_tag=${base_tag:-latest}

read -p "Do you want to generate a dynamic tag? (yes/no, default: yes): " dynamic_tag
dynamic_tag=${dynamic_tag:-yes}

# Step 3: Generate tag
if [[ $dynamic_tag == "yes" ]]; then
    tag=$(generate_tag "$base_tag")
else
    tag=$base_tag
fi

# Step 4: Build the image
build_image "$dockerfile" "$image_name" "$tag"

# Step 5: Push the image (optional)
read -p "Do you want to push the image to a registry? (yes/no, default: no): " push
push=${push:-no}

if [[ $push == "yes" ]]; then
    push_image "$image_name" "$tag"
fi

echo -e "${CHECK} Script execution completed."

Step-by-Step Explanation

1. Checking Prerequisites

The script first ensures that Docker is installed:

if ! command -v docker &> /dev/null; then

If Docker is unavailable, the script exits with an error.

2. Input Collection

The script collects inputs for:

  1. Dockerfile Path: Defaults to ./Dockerfile if none is specified.
  2. Image Name: Mandatory for identifying the container image.
  3. Base Tag: Defaults to latest if not specified.
  4. Dynamic Tagging: Combines the base tag with a timestamp and Git commit hash.

3. Building the Image

The docker build command builds the container image:

docker build -f "$dockerfile" -t "$image_name:$tag" .
  • -f: Specifies the Dockerfile.
  • -t: Tags the image with the format image_name:tag.

4. Dynamic Tag Generation

Dynamic tags include:

  • Base Tag: User-defined base version.
  • Timestamp: Ensures unique tagging.
  • Git Hash: Adds version control information if available.

For example:

base_tag: v1
timestamp: 20250109093000
git_hash: abc123
final_tag: v1-20250109093000-abc123

5. Pushing the Image

The docker push command pushes the image to the registry:

docker push "$image_name:$tag"

Make sure you are authenticated with the registry before pushing.


Examples

1. Build and Tag an Image

  1. Run the script:
    ./build_and_tag.sh
    
  2. Provide inputs:
    Enter the path to your Dockerfile (default: ./Dockerfile): 
    Enter the name of the image (e.g., myapp): myapp
    Enter the base tag for the image (e.g., v1): v1
    Do you want to generate a dynamic tag? (yes/no, default: yes): yes
    
  3. Output:
    ℹ Building the Docker image: myapp:v1-20250109093000-abc123
    ✔ Image built successfully: myapp:v1-20250109093000-abc123
    

2. Push the Image

  1. When prompted, choose to push the image:
    Do you want to push the image to a registry? (yes/no, default: no): yes
    
  2. Output:
    ℹ Pushing the image: myapp:v1-20250109093000-abc123 to the registry
    ✔ Image pushed successfully: myapp:v1-20250109093000-abc123
    

Technical Details

1. Image Tagging Best Practices

  • Use meaningful tags like v1, stable, or dev.
  • Include dynamic elements (timestamps, Git hashes) to differentiate builds.
  • Follow the <repository>/<image>:<tag> convention.

2. Authenticating with a Registry

  • Docker Hub:
    docker login
    
  • AWS Elastic Container Registry (ECR):
    aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account_id>.dkr.ecr.<region>.amazonaws.com
    
  • Google Container Registry (GCR):
    gcloud auth configure-docker
    

3. CI/CD Integration

Integrate this script into CI/CD pipelines for automated image building and deployment. For example:

  • Jenkins Pipeline:
    sh './build_and_tag.sh'
    
  • GitHub Actions:
    - name: Build and Push Docker Image
      run: ./build_and_tag.sh
    

Scenarios

Scenario 1: Automated Nightly Builds

Schedule the script to run nightly using cron:

0 3 * * * /path/to/build_and_tag.sh

Scenario 2: Multi-Environment Support

Modify the script to accept environment-specific arguments (e.g., dev, prod) and push images to different registries.

Scenario 3: Multi-Stage Builds

Extend the script to support multi-stage Docker builds for optimized images.


Benefits of This Script

  1. Consistency: Ensures every image follows a structured build and tagging process.
  2. Automation: Eliminates manual errors in building and tagging images.
  3. Scalability: Easily integrates with CI/CD pipelines.

This script is a robust and reusable solution for automating container image workflows. Let me know if you’d like additional enhancements or explanations!

 

Implementing Container Image Building and Tagging in Google Cloud Platform (GCP)

Google Cloud Platform (GCP) provides the Google Container Registry (GCR) and Artifact Registry for managing container images. These registries integrate seamlessly with Google Kubernetes Engine (GKE) and other GCP services. This guide explains how to automate container image building, tagging, and pushing using GCP tools.


Steps to Implement in GCP

1. Set Up GCP Environment

  1. Enable Required APIs: Ensure the following APIs are enabled in your GCP project:
    • Container Registry API
    • Artifact Registry API

    Use the gcloud CLI to enable these APIs:

    gcloud services enable containerregistry.googleapis.com
    gcloud services enable artifactregistry.googleapis.com
    
  2. Install and Configure gcloud: Install the gcloud CLI and authenticate with your GCP account:
    gcloud auth login
    gcloud config set project <PROJECT_ID>
    
  3. Enable Docker Authentication: Configure Docker to use gcloud for authentication with GCR or Artifact Registry:
    gcloud auth configure-docker
    

2. Create a Container Image Registry

  1. Using Container Registry (GCR): GCR repositories are created automatically when you push your first image. The format is:
    gcr.io/<PROJECT_ID>/<IMAGE_NAME>
    
  2. Using Artifact Registry: If you prefer Artifact Registry (recommended for new projects):
    • Create a repository:
      gcloud artifacts repositories create <REPOSITORY_NAME> \
        --repository-format=docker \
        --location=<REGION>
      
    • Use the following format for your images:
      <REGION>-docker.pkg.dev/<PROJECT_ID>/<REPOSITORY_NAME>/<IMAGE_NAME>
      

3. Automate Image Building and Tagging

Use the following bash script to build, tag, and push images to GCP registries:

#!/bin/bash

# Automate Container Image Building, Tagging, and Pushing in GCP
# Author: [Your Name]
# Date: [Date]
# Version: 1.0

# Icons for feedback
CHECK="\u2714" # ✔
CROSS="\u274C" # ✘
INFO="\u2139"  # ℹ

# Function: Check if Docker is installed
function check_docker() {
    if ! command -v docker &> /dev/null; then
        echo -e "${CROSS} Error: Docker is not installed. Please install Docker."
        exit 1
    fi
    echo -e "${CHECK} Docker is installed."
}

# Function: Build and tag the Docker image
function build_and_tag_image() {
    local dockerfile=$1
    local image_name=$2
    local tag=$3

    if [[ ! -f "$dockerfile" ]]; then
        echo -e "${CROSS} Error: Dockerfile not found at $dockerfile"
        exit 1
    fi

    echo -e "${INFO} Building Docker image: $image_name:$tag"
    docker build -f "$dockerfile" -t "$image_name:$tag" .

    if [[ $? -eq 0 ]]; then
        echo -e "${CHECK} Image built successfully: $image_name:$tag"
    else
        echo -e "${CROSS} Error: Image build failed."
        exit 1
    fi
}

# Function: Push the Docker image to GCP
function push_image_to_gcp() {
    local image_name=$1
    local tag=$2

    echo -e "${INFO} Pushing image: $image_name:$tag to GCP"
    docker push "$image_name:$tag"

    if [[ $? -eq 0 ]]; then
        echo -e "${CHECK} Image pushed successfully: $image_name:$tag"
    else
        echo -e "${CROSS} Error: Failed to push the image."
        exit 1
    fi
}

# Function: Generate a dynamic tag
function generate_dynamic_tag() {
    local base_tag=$1
    local timestamp=$(date +"%Y%m%d%H%M%S")
    echo "${base_tag}-${timestamp}"
}

# Main script starts here
echo "=== GCP Container Image Automation Script ==="

# Step 1: Check prerequisites
check_docker

# Step 2: Get user inputs
read -p "Enter the path to your Dockerfile (default: ./Dockerfile): " dockerfile
dockerfile=${dockerfile:-./Dockerfile}

read -p "Enter the GCP image name (e.g., gcr.io/<PROJECT_ID>/<IMAGE_NAME>): " image_name
if [[ -z "$image_name" ]]; then
    echo -e "${CROSS} Error: Image name cannot be empty."
    exit 1
fi

read -p "Enter the base tag for the image (e.g., v1): " base_tag
base_tag=${base_tag:-latest}

read -p "Do you want to generate a dynamic tag? (yes/no, default: yes): " dynamic_tag
dynamic_tag=${dynamic_tag:-yes}

# Step 3: Generate the tag
if [[ $dynamic_tag == "yes" ]]; then
    tag=$(generate_dynamic_tag "$base_tag")
else
    tag=$base_tag
fi

# Step 4: Build the image
build_and_tag_image "$dockerfile" "$image_name" "$tag"

# Step 5: Push the image to GCP
read -p "Do you want to push the image to GCP? (yes/no, default: yes): " push
push=${push:-yes}

if [[ $push == "yes" ]]; then
    push_image_to_gcp "$image_name" "$tag"
fi

echo -e "${CHECK} Script execution completed."

Step-by-Step Execution in GCP

1. Run the Script

Execute the script:

chmod +x build_and_tag_gcp.sh
./build_and_tag_gcp.sh

2. Example Input

Enter the path to your Dockerfile (default: ./Dockerfile): 
Enter the GCP image name (e.g., gcr.io/<PROJECT_ID>/<IMAGE_NAME>): gcr.io/my-project/my-app
Enter the base tag for the image (e.g., v1): v1
Do you want to generate a dynamic tag? (yes/no, default: yes): yes
Do you want to push the image to GCP? (yes/no, default: yes): yes

3. Output

✔ Docker is installed.
ℹ Building Docker image: gcr.io/my-project/my-app:v1-20250109093000
✔ Image built successfully: gcr.io/my-project/my-app:v1-20250109093000
ℹ Pushing image: gcr.io/my-project/my-app:v1-20250109093000 to GCP
✔ Image pushed successfully: gcr.io/my-project/my-app:v1-20250109093000
✔ Script execution completed.

Scenarios for Implementation

1. Continuous Integration/Continuous Deployment (CI/CD)

Integrate this script into CI/CD pipelines to automate image building and deployment.

  • GitHub Actions Workflow Example:
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - name: Authenticate with GCP
            run: gcloud auth configure-docker
          - name: Run build and push script
            run: ./build_and_tag_gcp.sh
    

2. Multi-Environment Builds

Customize the script to tag images based on environments:

  • Development: gcr.io/my-project/my-app:dev
  • Production: gcr.io/my-project/my-app:prod

Best Practices

  1. Use Artifact Registry: Artifact Registry provides better security and performance over GCR.
  2. Automate Authentication: Use service accounts for non-interactive workflows.
  3. Enable Image Scanning: Enable vulnerability scanning for container images in GCP.

Benefits of Automation in GCP

  1. Efficiency: Automates repetitive tasks like building and tagging images.
  2. Consistency: Ensures uniform tagging conventions across environments.
  3. Scalability: Easily integrates with CI/CD pipelines for large-scale deployments.

Let me know if you need additional configurations or examples!

Related articles

How to Configure Autoscaling in GCP

⚙️How to Configure Autoscaling in GCP Optimize your GCP workloads by dynamically scaling your resources to handle traffic spikes...

How to Install Python3 on Ubuntu 22.04

How to Install Python3 on Ubuntu 22.04 This step-by-step guide demonstrates how to install Python3 on Ubuntu 22.04. Afterward,...

How to use AWS Elastic Beanstalk for Application Deployment

🚀 How to use AWS Elastic Beanstalk for Application Deployment AWS Elastic Beanstalk is one of the easiest and...

How to Use Rsync on Linux to Synchronize Local and Remote Directories

How to Use Rsync on Linux to Synchronize Local and Remote Directories Rsync is a powerful command-line tool for...