Containers

You’re a DevOps engineer integrating a Dockerized Python application into a Jenkins CI/CD pipeline. The Dockerfile builds slowly, causing pipeline delays. How would you optimize the Dockerfile to speed up builds while maintaining functionality?

Difficulty: unrated

Source: bregman-arie/devops-exercises by Arie Bregman

Answer

To optimize a Dockerfile for faster CI/CD builds:

  1. Use a Smaller Base Image: Replace heavy images like python:3.9 with python:3.9-slim to reduce size and download time.
    FROM python:3.9-slim
    
  2. Leverage Layer Caching: Order instructions from least to most likely to change. Copy requirements.txt and install dependencies before copying the app code:
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    
  3. Minimize Layers: Combine related commands with && to reduce layers:
    RUN pip install -r requirements.txt && rm -rf /root/.cache/pip
    
  4. Use Multi-Stage Builds: If the app needs build tools, use a multi-stage build to keep the final image small:
    FROM python:3.9 AS builder
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    FROM python:3.9-slim
    COPY --from=builder /usr/local/lib/python3.9 /usr/local/lib/python3.9
    COPY . .
    CMD ["python", "app.py"]
    
  5. Test in Jenkins: Update the Jenkins pipeline to rebuild the image only when Dockerfile or code changes, using a cached image otherwise:
    pipeline {
        agent any
        stages {
            stage('Build Docker Image') {
                when { changeset "Dockerfile,**.py" }
                steps { sh 'docker build -t my-python-app .' }
            }
        }
    }