Self-hosted service
docker/build-push-action avatar
docker/build-push-action

docker/build-push-action: what the Git context default actually changes

GitHub Action to build and push Docker images with Buildx

5,409 stars736 forksTypeScriptApache-2.0

At a glance

What is it?
A review of Docker's Buildx action for GitHub Actions: how the Git context default, the docker-container driver and registry login fit together, and where the action is the wrong tool.
Who is it for?
Adopt docker/build-push-action when your image build already fits BuildKit: multi-platform output, registry login handled by docker/login-action, and a builder from docker/setup-buildx-action. Do not adopt it if you need the workflow to mutate files that the build then reads, because the default Git context ignores those mutations, including .dockerignore processing; switch to the context input with actions/checkout instead.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What docker/build-push-action removes from your workflow file

Without this action you write the build and push steps by hand: a docker buildx build invocation with the tag list, the platform list, the push flag and any cache flags assembled as shell. The action turns that into a declarative step. The README describes it as a GitHub Action to build and push Docker images with Buildx, with support for the features of the Moby BuildKit builder toolkit: multi-platform build, secrets, remote cache, and different builder deployment or namespacing options. The audience is anyone whose delivery pipeline ends in an image in a registry. If you build on a laptop and push manually, this adds nothing. If your image is the deployable artifact and it ships from CI, the action is the piece that decides which commit becomes which tag.

The Git context default is the design decision that matters most

By default the action does not read your checked-out working directory. It uses the Git context, so the build input is a URL of the form https://github.com/<owner>/<repo>.git#<ref>, derived from the event that triggered the workflow, and BuildKit clones it. That is why the README can say you do not need actions/checkout for the build step. The consequence is stated plainly: any file mutation in the steps that precede the build step is ignored, including processing of the .dockerignore file. A step that generates a version file, rewrites a lockfile or filters files before the build will have no effect on what BuildKit sees. Two escapes exist. Set the context input to . together with actions/checkout, which restores the usual local-directory semantics. Or keep the Git context and point at a subdirectory with the Handlebars template, writing context as "{{defaultContext}}:mysubdir". The second form is narrower than it looks: it selects a path inside the same Git ref, it does not give you a mutable working tree. Private repositories are handled through the automatic GitHub Token when building the current repository; authenticating against a different private repository requires a secret named GIT_AUTH_TOKEN passed through the secrets input. That naming is fixed, not a convention you can rename.

Installing it and getting one image to a registry

There is nothing to install locally. The action is consumed from the GitHub Marketplace page linked in the README, and the repository ships a compiled dist/index.cjs built by esbuild, which is what the runner executes. A minimal workflow needs a login step, a builder step and the build step. The README's Git context example uses docker/login-action@v4 with a username from vars.DOCKERHUB_USERNAME and a password from secrets.DOCKERHUB_TOKEN, then docker/setup-qemu-action@v4, then docker/setup-buildx-action@v4, then the build itself.

yaml
name: ci

on:
  push:

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Login to Docker Hub
        uses: docker/login-action@v4
        with:
          username: ${{ vars.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      -
        name: Build and push
        uses: docker/build-push-action@v7
        with:
          push: true
          tags: user/app:latest

After this runs, the tag user/app:latest exists in the registry. Note what is absent from the build step: no context, because the default applies, and no checkout step. If you want the build to read the files on the runner instead, add actions/checkout@v6 before the build and set context to a single dot. The README's path context example does exactly that, and the rest of the workflow is unchanged. QEMU is only needed when you want to build against platforms your runner does not natively execute; the README frames it as useful for adding emulation support, not as a requirement. The builder step is described as not required but recommended, which is worth reading carefully: without it you inherit whatever builder the runner provides, and the multi-platform and cache-export behaviour the README advertises depends on the docker-container driver that setup-buildx-action creates by default.

Where the defaults work against you

The Git context default is the sharpest edge, and it fails quietly. Nothing errors when a preceding step's file changes are skipped; the build simply uses the committed tree. A pipeline that injects a build number into a file, or that relies on a checkout-time filter, will produce an image that does not match the working directory the author inspected. The README flags this, but it is easy to skim past because the example workflows look like ordinary build steps. A second limitation is structural: the action is a wrapper. It does not create a builder, does not log in to a registry, and does not add emulation. Those are separate actions, and the README lists them as other actions used in its examples. If you expect a single step to cover the whole path from source to registry, you will be assembling three or four steps instead. A third is scope: the action builds and pushes images. It does not run your test suite against the built image, and the README's example index points to a separate test-before-push recipe rather than folding that into the action. If your workflow needs the image to be exercised before it reaches a registry, that ordering is yours to write.

Compared with calling docker buildx build in a run step

The honest alternative is not another action. It is a shell step that invokes docker buildx build with the flags you need. That approach gives you the full CLI surface with no input schema in between, and it makes the exact command visible in the workflow log. The difference in approach is where the configuration lives. With the shell step, every option is a flag you type, and version drift is your problem. With the action, options are named inputs declared in action.yml, and the action's own release cadence governs when new Buildx capabilities become reachable. The README's example index shows the breadth of that input surface: multi-platform images, secrets, pushing to multiple registries, tag and label management, cache management, export to Docker, validating build configuration, a local registry, sharing a built image between jobs, named contexts, copying an image between registries, and SBOM and provenance attestations. Reproducing all of that by hand is possible, and some teams prefer it precisely because nothing is hidden. The trade is maintenance: you own the flag set, and you own keeping it aligned with the Buildx version on the runner.

Version pinning, licence and what an upgrade costs

The action is released under Apache-2.0, and the repository carries a LICENSE file at the top level. The build script also runs generate-license-file to emit dist/licenses.txt from the dependency tree, so the bundled third-party notices ship inside the compiled artifact rather than only in the repository. That matters if your organisation scans the contents of action bundles. For legal questions about redistribution, read the licence text and the generated notices; nothing here is legal advice. On upgrades, the README pins major versions in its examples, showing v7 for this action while the companion actions appear as login-action@v4, setup-qemu-action@v4, setup-buildx-action@v4 and checkout@v6. Those majors move independently, so bumping this action alone can leave you on a builder action that does not expose a feature the new inputs expect. The published releases follow a minor cadence rather than a patch cadence, with v7.4.0 dated 2026-09-15, v7.3.0 dated 2026-07-01 and v7.2.0 dated 2026-05-21. The last push to the default branch was on 2026-09-21 and the repository is not archived, so the project is moving. Read the release notes for the minor you are jumping to before you move the tag, and check whether the input you depend on changed meaning rather than only gaining a sibling.

Editorial conclusion

Adopt docker/build-push-action when your image build already fits BuildKit: multi-platform output, registry login handled by docker/login-action, and a builder from docker/setup-buildx-action. Do not adopt it if you need the workflow to mutate files that the build then reads, because the default Git context ignores those mutations, including .dockerignore processing; switch to the context input with actions/checkout instead. Before rolling it out, verify the exact tag you pin (the README shows v7 while the related searches still ask about v4, v5 and v6), and confirm what your builder driver supports, since the README calls setup-buildx-action recommended rather than required and ties multi-platform and cache export to it.

Frequently asked questions

What is docker/build-push-action in GitHub Actions?

It is a GitHub Action that builds and pushes Docker images with Buildx, using the Moby BuildKit builder toolkit. The README lists multi-platform build, secrets, remote cache and different builder deployment or namespacing options among the supported features.

Should I use docker buildx or plain docker build?

This action is built on Buildx and BuildKit rather than the plain docker build path, and its multi-platform and cache-export behaviour depends on the docker-container driver that docker/setup-buildx-action creates by default. The README treats that setup action as recommended rather than required, so the choice is really about which builder your workflow provisions.

Do I need actions/checkout before docker/build-push-action?

Not for the build step, because the action uses the Git context by default and BuildKit performs the clone. You need actions/checkout only when you set the context input to a local path, and the README notes that in the Git context case any file mutation in preceding steps is ignored, including .dockerignore processing.

How do I authenticate to a private repository other than the current one?

The README states that building the current repository uses the automatic GitHub Token and needs nothing passed, but authenticating against another private repository requires a secret named GIT_AUTH_TOKEN supplied through the secrets input.

Which version of docker/build-push-action should I pin?

The README examples use docker/build-push-action@v7, and the published releases are v7.4.0, v7.3.0 and v7.2.0. The companion actions in the same examples are pinned at their own majors, so check them together rather than bumping this one in isolation.

Official sources

  1. docker/build-push-action on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/docker-build-push-action.svg)](https://hysenlabs.com/projects/docker-build-push-action)