-
Notifications
You must be signed in to change notification settings - Fork 885
Description
Issue Description
When a Containerfile contains duplicate stage names (FROM ... AS <name>):
--target <name>matches the first one- Without
--target, if the final stage depends on the duplicate stages, buildah builds all of them and uses the last one- (same for
--target <different stage>if this stage depends on the duplicate stages)
- (same for
Comparing to docker, buildah should probably match the last one in both cases (and skip building the earlier ones unless --skip-unused-stages=false).
Context: in Konflux, we do builds with no network access, which requires pre-pulling the images for FROM, COPY --from= etc. We had bugs in the pre-pull logic, so we're correcting it to match buildah behavior, and found this inconsistency.
Steps to reproduce the issue
Steps to reproduce the issue
Containerfile:
FROM scratch AS stage0
LABEL x="really stage 0"
FROM scratch AS stage0
LABEL x="actually stage 1"
FROM stage0Run:
$ buildah build -t test --target stage0 .
STEP 1/2: FROM scratch AS stage0
STEP 2/2: LABEL x="really stage 0"
COMMIT test
$ buildah inspect test:latest | jq .OCIv1.config.Labels
{
"io.buildah.version": "1.42.2",
"x": "really stage 0"
}
# without --target
$ buildah build -t test .
[1/3] STEP 1/2: FROM scratch AS stage0
[1/3] STEP 2/2: LABEL x="really stage 0"
Getting image source signatures
Copying blob 5f70bf18a086 skipped: already exists
Copying config 4723b20146 done |
Writing manifest to image destination
--> 4723b2014644
[2/3] STEP 1/2: FROM scratch AS stage0
[2/3] STEP 2/2: LABEL x="actually stage 1"
Getting image source signatures
Copying blob 5f70bf18a086 skipped: already exists
Copying config c6c98af0b5 done |
Writing manifest to image destination
--> c6c98af0b568
[3/3] STEP 1/1: FROM c6c98af0b5683156d753a2a41e315c13fb0c808e9eec87a165b111932acd2079
[3/3] COMMIT test
$ buildah inspect test:latest | jq .OCIv1.config.Labels
{
"io.buildah.version": "1.42.2",
"x": "actually stage 1"
}
Repeat experiment with docker:
$ docker build -t test -f Containerfile --target stage0 .
$ docker inspect test:latest | jq '.[].Config.Labels'
{
"x": "actually stage 1"
}
$ docker build -t test -f Containerfile .
$ docker inspect test:latest | jq '.[].Config.Labels'
{
"x": "actually stage 1"
}
Note that docker logs for this Containerfile don't actually show which stages are being built, so to prove that it doesn't build the first stage0 at all, replace the first line in the Containerfile with: FROM image-does-not-exist:foo AS stage0 (which would fail if docker tried to build it)
Describe the results you received
--target <name>matches the first one- Without
--target, if the final stage depends on the duplicate stages, buildah builds all of them and uses the last one
Describe the results you expected
--target <name>matches the last one, same as docker- Without
--target, if the final stage depends on the duplicate stages, buildah builds and uses the last one, same as docker
buildah version output
Version: 1.42.2
Go Version: go1.24.10
Image Spec: 1.1.1
Runtime Spec: 1.2.1
CNI Spec: 1.1.0
libcni Version:
image Version: 5.38.0
Git Commit:
Built: Wed Dec 3 15:03:30 2025
OS/Arch: linux/amd64
BuildPlatform: linux/amd64buildah info output
{
"host": {
"CgroupVersion": "v2",
"Distribution": {
"distribution": "fedora",
"version": "42"
},
"MemFree": 14483775488,
"MemTotal": 33056059392,
"OCIRuntime": "crun",
"SwapFree": 8589930496,
"SwapTotal": 8589930496,
"arch": "amd64",
"cpus": 14,
"hostname": "acmiel-thinkpadx1carbongen12.tpbc.csb",
"kernel": "6.18.13-100.fc42.x86_64",
"os": "linux",
"rootless": true,
"uptime": "1h 20m 26.46s (Approximately 0.04 days)",
"variant": ""
},
"store": {
"ContainerStore": {
"number": 5
},
"GraphDriverName": "overlay",
"GraphImageStore": "",
"GraphOptions": null,
"GraphRoot": "/home/acmiel/.local/share/containers/storage",
"GraphStatus": {
"Backing Filesystem": "btrfs",
"Native Overlay Diff": "true",
"Supports d_type": "true",
"Supports shifting": "false",
"Supports volatile": "true",
"Using metacopy": "false"
},
"GraphTransientStore": false,
"ImageStore": {
"number": 122
},
"RunRoot": "/run/user/105500/containers"
}
}Provide your storage.conf
[storage]
driver = "overlay"
runroot = "/run/containers/storage"
graphroot = "/var/lib/containers/storage"
[storage.options]
additionalimagestores = [
"/usr/lib/containers/storage",
]
pull_options = {enable_partial_images = "true", use_hard_links = "false", ostree_repos=""}
[storage.options.overlay]
mountopt = "nodev,metacopy=on"Upstream Latest Release
Yes
Additional environment details
No response
Additional information
No response