Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
20 KiB
About
GitHub Action to build and push Docker images with Buildx.
💡 See also:
- login action
- setup-buildx action
- setup-qemu action
Usage
This action uses our setup-buildx action that extends the
docker build
command named buildx with the full support of the features
provided by Moby BuildKit builder toolkit. This includes multi-arch build,
build-secrets, remote cache, etc. and different builder deployment/namespacing options.
Git context
The default behavior of this action is to use the Git context invoked by your workflow.
Show workflow
name: ci
on:
push:
branches: master
jobs:
main:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
If you use this action in a private repository, you have to pass the GitHub Token
as a secret named GIT_AUTH_TOKEN
to be able to authenticate against it with buildx:
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
secrets: |
GIT_AUTH_TOKEN=${{ github.token }}
⚠️ Subdir for Git context is not yet supported. For the moment you can use the path context.
Path context
You can also use the PATH
context alongside the actions/checkout
action.
Show workflow
name: ci
on:
push:
branches: master
jobs:
path-context:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386
push: true
tags: user/app:latest
Isolated builders
Show workflow
name: ci
on:
push:
branches: master
jobs:
multi-builders:
runs-on: ubuntu-latest
steps:
-
uses: docker/setup-buildx-action@v1
id: builder1
-
uses: docker/setup-buildx-action@v1
id: builder2
-
name: Builder 1 name
run: echo ${{ steps.builder1.outputs.name }}
-
name: Builder 2 name
run: echo ${{ steps.builder2.outputs.name }}
-
name: Build against builder1
uses: docker/build-push-action@v2
with:
builder: ${{ steps.builder1.outputs.name }}
target: mytarget1
-
name: Build against builder2
uses: docker/build-push-action@v2
with:
builder: ${{ steps.builder2.outputs.name }}
target: mytarget2
Multi-platform image
Show workflow
name: ci
on:
push:
branches: master
jobs:
multi:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: true
tags: |
user/app:latest
user/app:1.0.0
Advanced usage
Local registry
For testing purposes you may need to create a local registry to push images into.
Show workflow
name: ci
on:
push:
branches: master
jobs:
local-registry:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
-
name: Build and push to local registry
uses: docker/build-push-action@v2
with:
push: true
tags: localhost:5000/name/app:latest
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:latest
Leverage GitHub cache
You can leverage GitHub cache using actions/cache with this action.
Show workflow
name: ci
on:
push:
branches: master
jobs:
github-cache:
runs-on: ubuntu-latest
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
Complete workflow
If you come from v1
and you want an
"automatic" tag management through Git reference and OCI Image Format Specification
for labels, you will have to do it in a dedicated step for now.
The following workflow with the Prepare
step will generate some outputs
to handle tags and labels based on GitHub actions events. This is just an example to show many cases that you
might want to use:
Event | Ref | Commit SHA | Docker Tag | Pushed |
---|---|---|---|---|
schedule |
nightly |
Yes | ||
pull_request |
refs/pull/2/merge |
a123b57 |
pr-2 |
No |
push |
refs/heads/<default_branch> |
676cae2 |
sha-676cae2 , edge |
Yes |
push |
refs/heads/dev |
cf20257 |
sha-cf20257 , dev |
Yes |
push |
refs/heads/my/branch |
a5df687 |
sha-a5df687 , my-branch |
Yes |
push tag |
refs/tags/v1.2.3 |
v1.2.3 , v1.2 , v1 , latest |
Yes |
Show workflow
name: ci
on:
schedule:
- cron: '0 10 * * *' # everyday at 10am
push:
branches:
- '**'
tags:
- 'v*.*.*'
pull_request:
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Prepare
id: prep
run: |
DOCKER_IMAGE=name/app
VERSION=noop
if [ "${{ github.event_name }}" = "schedule" ]; then
VERSION=nightly
elif [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; then
VERSION=edge
fi
elif [[ $GITHUB_REF == refs/pull/* ]]; then
VERSION=pr-${{ github.event.number }}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
MINOR=${VERSION%.*}
MAJOR=${MINOR%.*}
TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR},${DOCKER_IMAGE}:${MAJOR},${DOCKER_IMAGE}:latest"
elif [ "${{ github.event_name }}" = "push" ]; then
TAGS="$TAGS,${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}"
fi
echo ::set-output name=version::${VERSION}
echo ::set-output name=tags::${TAGS}
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=${{ github.event.repository.description }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.licenses=${{ github.event.repository.license.spdx_id }}
Update DockerHub repo description
You can update the Docker Hub repository description using a third-party action called Docker Hub Description with this action.
Show workflow
name: ci
on:
push:
branches: master
jobs:
main:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
-
name: Update repo description
uses: peter-evans/dockerhub-description@v2
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
DOCKERHUB_REPOSITORY: user/app
Customizing
inputs
Following inputs can be used as step.with
keys
Name | Type | Description |
---|---|---|
builder |
String | Builder instance (see setup-buildx action) |
context |
String | Build's context is the set of files located in the specified PATH or URL (default Git context) |
file |
String | Path to the Dockerfile (default Dockerfile ) |
build-args |
List | List of build-time variables |
labels |
List | List of metadata for an image |
tags |
List | List of tags |
pull |
Bool | Always attempt to pull a newer version of the image (default false ) |
target |
String | Sets the target stage to build |
allow |
List | List of extra privileged entitlement (eg. network.host,security.insecure ) |
no-cache |
Bool | Do not use cache when building the image (default false ) |
platforms |
List | List of target platforms for build |
load |
Bool | Load is a shorthand for --output=type=docker (default false ) |
push |
Bool | Push is a shorthand for --output=type=registry (default false ) |
outputs |
CSV | List of output destinations (format: type=local,dest=path ) |
cache-from |
CSV | List of external cache sources (eg. type=local,src=path/to/dir ) |
cache-to |
CSV | List of cache export destinations (eg. type=local,dest=path/to/dir ) |
secrets |
CSV | List of secrets to expose to the build (eg. key=value , GIT_AUTH_TOKEN=mytoken ) |
List
type can be a comma or newline-delimited stringtags: name/app:latest,name/app:1.0.0
tags: | name/app:latest name/app:1.0.0
CSV
type must be a newline-delimited stringcache-from: user/app:cache
cache-from: | user/app:cache type=local,src=path/to/dir
outputs
Following outputs are available
Name | Type | Description |
---|---|---|
digest |
String | Image content-addressable identifier also called a digest |
Troubleshooting
While pushing to a registry, you may encounter these kinds of issues:
failed commit on ref "layer-sha256:...": invalid content digest in response: invalid checksum digest format
failed commit on ref "layer-sha256:...": no response
failed commit on ref "manifest-sha256:...": unexpected status: 401 Unauthorized
unexpected response: 401 Unauthorized
These issues are not directly related to this action but are rather linked to buildx, buildkit, containerd or the registry on which you're pushing your image. The quality of error message depends on the registry and are usually not very informative.
To help you solve this, you should first enable debugging in the setup-buildx action step:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
buildkitd-flags: --debug
Next you can test pushing with containerd using this workflow.
Do not forget to set ctr --debug
for the pushing step. If it works then open an issue on
buildkit repository.
Keep up-to-date with GitHub Dependabot
Since Dependabot
has native GitHub Actions support,
to enable it on your GitHub repo all you need to do is add the .github/dependabot.yml
file:
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
Limitation
This action is only available for Linux virtual environments.