Skip to content

imagebuildah: default RUN --mount type to bind for cache checksums - #6957

Merged
TomSweeneyRedHat merged 1 commit into
podman-container-tools:mainfrom
MayukhSobo:fix-mount-bind-default-podman-29126
Jul 14, 2026
Merged

imagebuildah: default RUN --mount type to bind for cache checksums#6957
TomSweeneyRedHat merged 1 commit into
podman-container-tools:mainfrom
MayukhSobo:fix-mount-bind-default-podman-29126

Conversation

@MayukhSobo

Copy link
Copy Markdown
Contributor

/kind bug

What this PR does / why we need it:

getFromAndSourceKeysFromMountFlag() parses a RUN --mount=... flag to decide whether getCreatedBy() should checksum the mounted content for the build-cache fingerprint. When a Dockerfile omits type= (the normal, idiomatic way to write a bind mount, since bind is the implicit default per the Dockerfile/BuildKit mount syntax), this parser left Type empty instead of defaulting it to "bind" — unlike buildah's other mount parser, the one that actually sets mounts up (internal/volumes/volumes.go's getMounts(), which does default mountType := define.TypeBind).

Because of that, getCreatedBy()'s if mountInfo.Type != "bind" { continue } check skipped checksumming the mounted content for any implicit-bind mount — whether sourced from the build context, another build stage, an image, or an additional build context. Two builds with identical Dockerfile text but different mounted file content ended up with an identical cache key, so the second build silently reused the first build's cached layer instead of picking up the new content.

The fix defaults the parsed mount type to define.TypeBind, matching the default already used by the real mount-setup parser. type=cache and type=tmpfs mounts remain correctly excluded from checksumming — that's intentional, since persisting regardless of build content is their whole purpose.

How to verify it

  1. Create a build context with a file, e.g. data.txt containing foo.
  2. Build a Dockerfile that uses an implicit bind mount (no type=):
    FROM alpine
    RUN --mount=src=data.txt,target=/tmp/data.txt cat /tmp/data.txt
    
    using buildah build --layers . — it prints foo.
  3. Change data.txt to contain bar, then rebuild the same Dockerfile with --layers again.
  4. Before this fix: the second build reuses the cached layer and still prints foo, even though the mounted file changed. After this fix: the cache is correctly invalidated and the second build prints bar.

A unit test was also added, TestGetFromAndSourceKeysFromMountFlag in imagebuildah/util_test.go, which fails without this fix (asserts Type defaults to "bind" when type= is omitted) and passes with it:

go test -run TestGetFromAndSourceKeysFromMountFlag ./imagebuildah/...

Which issue(s) this PR fixes:

Fixes podman-container-tools/podman#29126

Special notes for your reviewer:

This bug was reported against podman (originally podman-container-tools/podman#29126, now podman-container-tools/podman#29126 after the org transfer), but root-caused to buildah — podman build vendors buildah's imagebuildah package. There is no separate buildah-side issue tracking this; per CONTRIBUTING.md, a PR alone is sufficient as long as its description includes what an issue report would (repro steps + root cause), which this PR provides above.

Does this PR introduce a user-facing change?

Fixed a build-cache bug where `RUN --mount` flags that omit `type=` (an implicit bind mount) were not checksummed for cache invalidation, causing builds to silently reuse a stale cached layer when only the mounted file's content changed.

getFromAndSourceKeysFromMountFlag() parses a RUN --mount=... flag to
decide whether getCreatedBy() should checksum the mounted content for
the build-cache fingerprint. When a Dockerfile omits type= (the
normal, idiomatic way to write a bind mount, since bind is the
implicit default), this parser left Type empty instead of defaulting
it to "bind", unlike buildah's other mount parser used to actually set
up mounts (internal/volumes/volumes.go), which does default to
define.TypeBind.

Because of that, getCreatedBy()'s "if mountInfo.Type != bind { continue }"
check skipped checksumming the mounted content for any implicit-bind
mount, whether sourced from the build context, another build stage, an
image, or an additional build context. Two builds with identical
Dockerfile text but different mounted file content ended up with an
identical cache key, so the second build silently reused the first
build's cached layer instead of picking up the new content.

type=cache and type=tmpfs mounts are still correctly excluded from
checksumming; that exclusion is intentional, since their purpose is to
persist regardless of build content.

Reported downstream at
podman-container-tools/podman#29126.

Signed-off-by: MayukhSobo <mayukh2012@hotmail.com>

@nalind nalind left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@TomSweeneyRedHat

Copy link
Copy Markdown
Contributor

Nice! TYVM!
LGTM

@TomSweeneyRedHat

Copy link
Copy Markdown
Contributor

/lgtm

@TomSweeneyRedHat
TomSweeneyRedHat merged commit ce4012e into podman-container-tools:main Jul 14, 2026
44 of 46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build contexts get mixed up

3 participants