docs icon indicating copy to clipboard operation
docs copied to clipboard

Using `LABEL` in multi-stage builds

Open dreua opened this issue 6 months ago • 2 comments

Is this a docs issue?

  • [x] My issue is about the documentation content or website

Type of issue

I can't find what I'm looking for

Description

I came upon this multi-stage Dockerfile which declares LABELs in the build stage and then continues to copy the binary to a new scratch image. From my inspection and rebuilds with podman that is a bug as the labels only appear in the resulting image after I moved the statements to the bottom of the file. Therefore my question which the current documentation does not answer:

Are LABEL statements context specific, i.e. only applied to the current building context and not to the images created by subsequent FROM statements? (It looks to me like they are.)

Location

https://docs.docker.com/reference/dockerfile/

Suggestion

If my assumption is correct that should be made clearer in the specification, maybe give some guidance on where or where not to put the LABEL statements in order to avoid mistakes.

dreua avatar Jun 28 '25 15:06 dreua

The Dockerfile you linked sets the labels for the first stage (build); the second stage starts FROM scratch, and does not inherit from the build config, other than copying artifacts from that stage (through COPY --from), which means that stage does not inherit LABELs from the other stage.

FROM docker.io/library/golang:1.23-bookworm AS build

# Set some labels
# io.containers.autoupdate label will instruct podman to reach out to the corres
# corresponding registry to check if the image has been updated. If an image
# must be updated, Podman pulls it down and restarts the systemd unit executing
# the container. See podman-auto-update(1) for more details, or
# https://docs.podman.io/en/latest/markdown/podman-auto-update.1.html
LABEL io.containers.autoupdate=registry
LABEL org.opencontainers.image.authors="[email protected]"

RUN apt-get update && apt-get install -y tor-geoipdb

ADD . /app

WORKDIR /app/proxy
RUN go get
RUN CGO_ENABLED=0 go build -o proxy -ldflags '-extldflags "-static" -w -s'  .

FROM scratch

COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /usr/share/tor/geoip* /usr/share/tor/
COPY --from=build /app/proxy/proxy /bin/proxy

ENTRYPOINT [ "/bin/proxy" ]

The labels would be present in the image produced when explicitly building the build stage as final image, e.g.

docker build -t myimage --target=build .

thaJeztah avatar Jul 20 '25 20:07 thaJeztah

Yeah, that is how I figured that it would be. I think that the documentation could be more explicit in this regard, but maybe this is just something you need to understand form context? Feel free to close this if you don't think there is anything to improve here.

On further thought I feel like the Dockerfile syntax is not really ideal as it doesn't really show the importance and special meaning of the FROM command. If I understand correctly, each FROM starts a whole new context and all subsequent statements (until the next FROM) will be executed in that statement. In other languages you'd show this by opening a visual block after each from by using brackets, indentation, or both. I don't know all the Dockerfile commands but I think this applies to all of them?

dreua avatar Jul 21 '25 10:07 dreua