Happy Employees == Happy ClientsCAREERS AT DEPT®
DEPT® Engineering Blogdocker

How to speed up Docker builds in GitHub Actions

Are your Docker builds slow in GitHub Actions? Here's how to speed it up with the built-in GitHub Actions cache.

Are your Docker builds slow in GitHub Actions? Here's how to speed it up with the built-in GitHub Actions cache.

Official Docker Action

Docker published an official GitHub Actions cache integration along with an official GitHub Actions plugin.

Here's how to use both and turn on the GitHub Actions cache to speed up your Docker builds. The trick is to set cache-from and cache-to to type=gha

      -
        name: Build Tag and Push Docker image
        uses: docker/build-push-action@v4
        with:
          file: nextjs-blog/docker/Dockerfile
          context: nextjs-blog
          tags: ${{ steps.dockermeta.outputs.tags }}
          labels: ${{ steps.dockermeta.outputs.labels }}
          push: true
          cache-from: type=gha
          cache-to: type=gha,mode=max

GHA cache for Docker

A complete working example is here at
https://github.com/deptagency/engineering-blog-github-actions/blob/main/.github/workflows/docker-nextjs.yml

How do you know that the cache is working? The Docker build output will tell you. Your first Docker build will be slower because it's populating the cache. For subsequent builds, you will see a Docker output similar to:

#10 [deps 1/4] RUN apk add --no-cache libc6-compat
#10 CACHED

See sample output here
https://github.com/deptagency/engineering-blog-github-actions/actions/runs/5895631079/job/15991811696#step:7:176

‼️
GitHub Action cache has a current limit of 10 GB.Large Docker images can quickly outgrow this size limitation.

Alternatives

GHA local cache

If you want more control over your GitHub cache, you can use Docker local cache. Just set cache-from and cache-to to type=local .

      -
        name: GitHub Actions Cache Docker layers
        uses: actions/cache@v3
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      -
        name: Build Tag and Push Docker image
        uses: docker/build-push-action@v4
        with:
          file: nextjs-blog/docker/Dockerfile
          context: nextjs-blog
          tags: ${{ steps.dockermeta.outputs.tags }}
          labels: ${{ steps.dockermeta.outputs.labels }}
          push: true
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

Local cache for Docker

A complete working example is here at
https://github.com/deptagency/engineering-blog-github-actions/blob/main/.github/workflows/docker-nextjs-actions-cache.yml

Registry cache

You can use the container registry, such as GitHub Container Registry or AWS ECR, to store the image build cache.

For this example, we will use the AWS ECR by setting the cache to type=registry

      -
        name: Build Tag and Push Docker image
        uses: docker/build-push-action@v4
        with:
          file: nextjs-blog/docker/Dockerfile
          context: nextjs-blog
          tags: ${{ steps.dockermeta.outputs.tags }}
          labels: ${{ steps.dockermeta.outputs.labels }}
          pull: true
          push: true
          cache-from: type=registry,ref=${{ env.ECR_FULL_REPO }}:dockercache
          cache-to: type=registry,ref=${{ env.ECR_FULL_REPO }}:dockercache,mode=max,image-manifest=true

ECR Registry cache for Docker

A complete working example for GHCR is here at
https://github.com/deptagency/engineering-blog-github-actions/blob/main/.github/workflows/docker-nextjs-registry-cache-ghcr.yml

A complete working example for AWS ECR is here at
https://github.com/deptagency/engineering-blog-github-actions/blob/main/.github/workflows/docker-nextjs-registry-cache.yml