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
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