Speed Up Your Build with caching in Github Action.

Save between 10% and 90% of your build time!

As a DevOps professional, automation is a daily essential—but optimizing our workflow time is always challenging. Reducing the duration of testing, building, and deployment processes can be a nightmare. In this article, we'll show you how caching in GitHub Actions can transform your pipelines and dramatically speed up your builds.

Why Use Caching?

Caching prevents repetitive work by reusing previously built layers or dependencies. This means:

  • Faster Builds: Significant time savings.

  • Lower Resource Usage: Less CPU and bandwidth consumption.

  • Enhanced Productivity: Quicker development and deployment cycles.

To illustrate the impact of caching, we use a Django application. To highlight the time gap, we add the heavy library scikit-learn to our requirements.txt:

asgiref
Django
sqlparse
scikit-learn  # Heavy library to observe the time difference

Workflow with Cache

name: Install dependencies witht cache
run-name: Install dependencies with  cache

on: [push, pull_request]


jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Buildx
        uses: docker/setup-buildx-action@v2
        with:
          driver: docker-container

      - name: Restore Cache
        uses: actions/cache@v3
        id: docker-cache
        with:
          path: .cache/docker
          key: docker-cache-${{ github.sha }}
          restore-keys: |
            docker-cache-

      - name: Build Image
        uses: docker/build-push-action@v4
        with:
          context: tp_cache
          file: tp_cache/Dockerfile
          target: with_cache
          tags: image-with-cache
          cache-from: type=local,src=.cache/docker
          cache-to: type=local,mode=max,dest=.cache/docker

Workflow Without Cache

name: Install dependencies without pip cache
run-name: Install dependencies without pip cache

on: [push, pull_request]


jobs:
  install-dependencies:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4


      - name: Build Image
        uses: docker/build-push-action@v4
        with:
          context: tp_cache
          file: tp_cache/Dockerfile
          target: without_cache
          tags: image-without-cache

Case 1: Django Application – Installing Dependencies via a Virtual Environment

The Dockerfile

We use the python:3.12-slim image (Debian-based) to create the virtual environment, install pip libraries, and run the server:

FROM python:3.12-slim AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential gcc
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install -r requirements.txt


FROM python:3.12-slim AS with_cache
COPY --from=compile-image /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]


FROM python:3.12-slim AS without_cache
COPY --from=compile-image /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Result:

Using cache saves about 10% of the build time.

Case 2: Building a Pip Library from Source on Alpine

In this scenario, we test building a pip library from source (tar.gz) using Alpine as the build environment. By default, Alpine compiles Python packages from source, which is usually slower.

The requirements.txt, workflows remains the same:

The Dockerfile

We use the python:3.12-alpine image (Alpine-based) to create the virtual environment, install pip libraries:

FROM python:3.13.2-alpine3.21 AS compile-image

RUN apk update && apk add --no-cache \
    build-base \
    gcc \
    g++ \
    python3-dev \
    py3-pip
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install -r requirements.txt



FROM python:3.12-slim AS with_cache
COPY --from=compile-image /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]



FROM python:3.12-slim AS without_cache
COPY --from=compile-image /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Result:

In this case, caching can save up to 80% of the build time, as reusing precompiled layers eliminates the heavy source compilation on Alpine.

Conclusion

Using caching in GitHub Actions offers significant benefits:

  • Time Savings: Reduce build times by 10% to 90% depending on the scenario.

  • Resource Optimization: Lower CPU and bandwidth usage by avoiding repetitive compilations or installations.

  • Enhanced Productivity: Faster workflows mean quicker development and deployment cycles.

By smartly integrating caching into your pipelines, you not only accelerate your builds but also streamline your entire CI/CD process. Are you ready to supercharge your GitHub Actions builds?

Feel free to share your feedback and any tips you have on optimizing workflows further!👍