Skip to content

proposal: add client-side global dockerignore for local build contexts #3776

@crazy-max

Description

@crazy-max

The goal is to let users exclude machine-local junk such as .dev/, .idea/, editor swap files, and OS metadata from builds without requiring every repository to carry those rules in its checked-in .dockerignore. This is the same class of problem that Git solves with a global excludes file, but the right layer here is buildx, not the daemon.

I think this belongs in docker/buildx because buildx already owns client-side configuration and already decides how local contexts are prepared and synced to the builder.

A daemon-side implementation is the wrong shape for buildx users because the builder is often remote, containerized, or running in Kubernetes. In those cases, a builder-side home directory has nothing to do with the workstation that contains the local junk we actually want to exclude. A buildx-side implementation keeps the feature attached to the machine that is sending the context, which is the only place where this request makes consistent sense.

Buildx should read a global ignore file from $BUILDX_CONFIG/.dockerignore, with fallback to $DOCKER_CONFIG/buildx/.dockerignore.

This file should apply only to local directory contexts and local named contexts. It should not apply to remote Git contexts, remote tarball contexts, HTTP contexts, image contexts, or target: contexts in the first iteration.

The filtering should happen client-side before the local filesystem is synced to BuildKit. That keeps the behavior consistent across docker, docker-container, Kubernetes, and remote builders.

I think the semantics should be intentionally narrower than Git. A global buildx ignore should behave as an additive deny-list for client-side filtering, not as a fully mergeable ignore language with later re-includes. Once a path is dropped client-side, repo-local .dockerignore files obviously cannot bring it back. That tradeoff seems acceptable because this feature is aimed at personal workstation clutter, not project-owned files.

Repository .dockerignore files and Dockerfile-specific ignore files should continue to work exactly as they do today for paths that remain in the uploaded context. The proposal is not to replace repository ignore behavior, but to let buildx strip obvious client-local trash before the normal builder-side rules run.

This would remove a lot of pointless per-repo churn for a very common class of local-only files.

It would also make buildx more honest about the client and builder boundary. If a user wants to exclude files that exist only because of how they work locally, the buildx client is the correct place to express that policy.

The buildx config directory is already the obvious place for this kind of user-specific behavior, so the feature has a natural home and doesn't need to invent a new configuration surface.

This proposal overlaps with the long-running request for a global .dockerignore in moby, especially moby/moby#12843, and it also fits under the broader .dockerignore tracking issue in moby/moby#40319.

There are also related .dockerignore behavior issues in the CLI, including docker/cli#2847 and docker/cli#3043, which show that users keep running into gaps between repository ignore rules and what the local client actually sends.

On the BuildKit side, moby/buildkit#1942 and moby/buildkit#4439 show that users want finer control over what is present in context versus what is consumed by individual build steps. This proposal is narrower than those requests, but it lives in the same problem space.

On the buildx side, this also relates to issues that are really about client-side context handling and remote-builder behavior, such as #1765 and #2564. I think that is another reason to keep this proposal centered in buildx rather than pushing it down into daemon config.

I'm proposing a small and explicit feature here, not a redesign of .dockerignore.

The scope is a buildx-only, client-side global ignore file for local contexts, stored in the buildx config directory, applied before sync, and intentionally additive only. That seems like the smallest coherent change that solves the real user problem without dragging builder-side state or cross-repo policy into it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions