This action generates cache-from
and cache-to
inputs of docker/build-push-action for the effective cache strategy in the pull request based development flow.
docker/build-push-action supports the cache management using Buildx (BuildKit). It can import and export a cache by the following parameters:
cache-from: type=registry,ref=REGISTRY/REPOSITORY:TAG
cache-to: type=registry,ref=REGISTRY/REPOSITORY:TAG,mode=max
If a same tag is used in the pull request based development flow, it will cause a cache miss. For example,
- Initially, the cache points to main branch
- When a pull request B is opened,
- It imports the cache of main branch
- The cache hits
- It exports the cache of pull request B
- When a pull request C is opened,
- It imports the cache of pull request B
- The cache misses
- It exports the cache of pull request C
- When the pull request B is merged into main,
- It imports the cache of pull request C
- The cache misses
- It exports the cache of main branch
Therefore, it needs to prevent the cache pollution caused by a pull request.
Keep a cache tag tracking the corresponding branch.
When the main branch is pushed, it imports a cache from the main tag. It finally exports a cache to the main tag for the future build.
cache-from: type=registry,ref=REGISTRY/REPOSITORY:main
cache-to: type=registry,ref=REGISTRY/REPOSITORY:main,mode=max
When a pull request is created or updated, it only imports a cache from the main tag. It does not export a cache to the main tag to prevent the cache pollution.
cache-from: type=registry,ref=REGISTRY/REPOSITORY:main
cache-to:
If the base branch of the pull request is not main, it imports both base tag and main tag.
cache-from: |
type=registry,ref=REGISTRY/REPOSITORY:base
type=registry,ref=REGISTRY/REPOSITORY:main
cache-to:
Here is the diagram of this cache strategy.
This action generates the cache parameters by this strategy.
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
- uses: docker/build-push-action@v2
with:
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
Here is an example to manage a cache in GHCR (GitHub Container Registry).
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ghcr.io/${{ github.repository }}:main
ghcr.io/${{ github.repository }}:pr-1
ghcr.io/${{ github.repository }}/cache:main
You can set a tag suffix to store both image and cache into the same repository.
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}
flavor: suffix=-cache
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ghcr.io/${{ github.repository }}:main
ghcr.io/${{ github.repository }}:main-cache
ghcr.io/${{ github.repository }}:pr-1
Amazon ECR now supports the cache manifest (aws/containers-roadmap#876).
You can pass the extra attribute image-manifest=true
.
Here is an example to manage a cache in Amazon ECR.
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
outputs:
image-uri: ${{ steps.ecr.outputs.registry }}/${{ github.repository }}@${{ steps.build.outputs.digest }}
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::ACCOUNT:role/ROLE
- uses: aws-actions/amazon-ecr-login@v1
id: ecr
- uses: docker/metadata-action@v5
id: metadata
with:
images: ${{ steps.ecr.outputs.registry }}/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ${{ steps.ecr.outputs.registry }}/${{ github.repository }}
suffix: -cache
extra-cache-to: image-manifest=true
- uses: docker/build-push-action@v5
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ACCOUNT.dkr.ecr.REGION.amazonaws.com/${{ github.repository }}:main
ACCOUNT.dkr.ecr.REGION.amazonaws.com/${{ github.repository }}:pr-1
ACCOUNT.dkr.ecr.REGION.amazonaws.com/${{ github.repository }}:main-cache
When a pull request is pushed, it can export a cache to a dedicated tag for the consecutive commits. It imports the cache from the dedicated tag when the pull request is pushed again.
cache-from: |
type=registry,ref=REGISTRY/REPOSITORY:pr-1
type=registry,ref=REGISTRY/REPOSITORY:main
cache-to: type=registry,ref=REGISTRY/REPOSITORY:pr-1,mode=max
Here is an example to enable the pull request cache feature.
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
pull-request-cache: true
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ghcr.io/${{ github.repository }}:main
ghcr.io/${{ github.repository }}:pr-1
ghcr.io/${{ github.repository }}/cache:main
ghcr.io/${{ github.repository }}/cache:pr-1
Note that it creates an image tag for every pull request. It is recommended to clean it when pull request is closed, or set a lifecycle policy into your container repository.
You can set a tag suffix to isolate caches for each architecture.
jobs:
build:
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
steps:
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
flavor: suffix=-${{ matrix.platform }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
flavor: suffix=-${{ matrix.platform }}
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
platforms: ${{ matrix.platform }}
It will create the following image tags:
ghcr.io/${{ github.repository }}:main-linux-amd64
ghcr.io/${{ github.repository }}:main-linux-arm64
ghcr.io/${{ github.repository }}:pr-1-linux-amd64
ghcr.io/${{ github.repository }}:pr-1-linux-arm64
ghcr.io/${{ github.repository }}/cache:main-linux-amd64
ghcr.io/${{ github.repository }}/cache:main-linux-arm64
You can set a tag prefix to store caches of multiple images into a single repository.
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}/microservice-name
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
flavor: prefix=microservice-name--
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ghcr.io/${{ github.repository }}/microservice-name:main
ghcr.io/${{ github.repository }}/microservice-name:pr-1
ghcr.io/${{ github.repository }}/cache:microservice-name--main
For a complex project, it needs to build multiple image tags from a branch. For example, it builds the following images when the main branch is pushed:
- Build an image tag
development
with the build-args of development environment - Build an image tag
staging
with the build-args of staging environment
In this case, it needs to separate the cache for each environment as follows:
- When the main branch is pushed,
- A job builds an image for the development environment.
It imports and exports a cache from/to
development
tag. - A job builds an image for the staging environment.
It imports and exports a cache from/to
staging
tag.
- A job builds an image for the development environment.
It imports and exports a cache from/to
- When a pull request is created or updated,
- A job builds an image for the pull request environment.
It imports a cache from
development
tag.
- A job builds an image for the pull request environment.
It imports a cache from
You can set a suffix to separate the caches for each environment.
jobs:
build:
strategy:
fail-fast: false
matrix:
environment:
- development
- staging
steps:
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
flavor: suffix=-${{ matrix.environment }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
cache-key: ${{ matrix.environment }}
cache-key-fallback: development
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
It will create the following image tags:
ghcr.io/${{ github.repository }}:development
ghcr.io/${{ github.repository }}:staging
ghcr.io/${{ github.repository }}/cache:development
ghcr.io/${{ github.repository }}/cache:staging
To ensure fast builds, BuildKit automatically caches the build result in its own internal cache. Additionally, BuildKit also supports exporting build cache to an external location, making it possible to import in future builds.
Ref: https://docs.docker.com/build/cache/backends/
You can set the cache-type
to configure the backend to use.
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
cache-type: inline # cache backend storage
Will generate the following outputs
cache-from: |
type=inline,ref=REGISTRY/REPOSITORY:pr-1
type=inline,ref=REGISTRY/REPOSITORY:main
cache-to: type=inline,ref=REGISTRY/REPOSITORY:pr-1,mode=max
The GitHub Actions cache utilizes the GitHub-provided Action's cache or other cache services supporting the GitHub Actions cache protocol. This is the recommended cache to use inside your GitHub Actions workflows, as long as your use case falls within the size and usage limits set by GitHub. ⚠ This is an experimental feature. The interface and behavior are unstable and may change in future releases.
Ref: https://docs.docker.com/build/cache/backends/gha/
You can set the cache type to gha
to use the GitHub Actions cache.
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
cache-type: gha
- uses: docker/build-push-action@v2
id: build
with:
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
Name | Default | Description |
---|---|---|
image |
(required) | Image repository to import/export cache |
cache-type |
registry |
Type of cache backend (for source and destination). Can be registry, local, inline, gha and s3 |
flavor |
- | Flavor (multiline string) |
extra-cache-from |
- | Extra flag to cache-from |
extra-cache-to |
- | Extra flag to cache-to |
pull-request-cache |
- | Import and export a pull request cache |
cache-key |
- | Custom cache key |
cache-key-fallback |
- | Custom cache key to fallback |
flavor
is mostly compatible with docker/metadata-action
except this action supports only prefix
and suffix
.
extra-cache-to
is added to cache-to
parameter only when it needs to export cache.
Note that cache-key
and cache-key-fallback
are experimental.
The specification may change in the future.
Name | Description |
---|---|
cache-from |
Parameter for docker/build-push-action |
cache-to |
Parameter for docker/build-push-action |
This action exports a cache on the following events:
push
event to a branch- Export a cache to the tag corresponding to the pushed branch
pull_request
event- Export a cache to the tag corresponding to the pull request number (only if
pull-request-cache
is set)
- Export a cache to the tag corresponding to the pull request number (only if
issue_comment
event to a pull request- Export a cache to the tag corresponding to the pull request number (only if
pull-request-cache
is set)
- Export a cache to the tag corresponding to the pull request number (only if
- Other events
- Export nothing
It imports a cache on the following events:
push
event to a branch- Import a cache from the tag corresponding to the pushed branch
pull_request
event- Import a cache from the tag corresponding to the pull request number
- Import a cache from the tag corresponding to the base branch
- Import a cache from the tag corresponding to the default branch
issue_comment
event to a pull request- Import a cache from the tag corresponding to the pull request number
- Import a cache from the tag corresponding to the base branch
- Import a cache from the tag corresponding to the default branch
- Other events
- Import a cache from the tag corresponding to the default branch