Copying labels from one stage to another

I’m using multi stage builds to create lightweight images of a C++ application.

Below a simplified example of the two Dockerfile:

First Dockerfile

FROM ubuntu:24.04 AS inter
LABEL version="Super label"
LABEL commit="abc123"
LABEL cmake.version="3.20"

RUN mkdir -p /tmp/
WORKDIR /tmp/
RUN touch first_stage.md

FROM inter AS final
LABEL project="My project"
RUN touch second_stage.md

Second Dockerfile

FROM my_test_1:latest
LABEL pipe="green"
RUN touch third_stage.md

FROM ubuntu:24.04 AS final_2
COPY --from=0 /tmp/ /tmp/

The second image is built from the first image.

How can I copy all labels from the inter_2 stage to the final_2 stage in my second Dockerfile?

I am afraid this is not going to work. You can only copy data from one stage (or image, or the build context) to your current stage.

In your case, using the my_test_1:latest image as base image for your final image doesn’t seem to make much sense, as it would inherit a lot of bloat as well.

It does make sense in my context (but not in the example)

Then I will try to write a file containing the labels during the image build so that I am able to retrieve all the labels in my final image.

But how would you set the labels? You would need to save a file on the host and dynamically generate a Dockerfile that sets the labels

I found a way without using a file for my GitLab CI

It copies all the labels from the source image and passes a list of --label arguments to docker build

.docker_build_args: &docker_build_args
  - DOCKER_BUILD_ARGS="--build-arg VERSION=$CI_COMMIT_REF_NAME --build-arg COMMIT=$CI_COMMIT_SHA"
  - DOCKER_LABEL_ARGS=$(docker inspect $CI_REGISTRY/$CI_PROJECT_NAMESPACE/project:$PLATFORM_TAG | jq -r '.[] | .Config.Labels | to_entries | map("--label \(.key)=\"\(.value | tostring | gsub("\""; "\\\""))\"") | join(" ")')
  - DOCKER_ARGS="$DOCKER_BUILD_ARGS $DOCKER_LABEL_ARGS"
build_image:
  stage: deploy
  image: docker:28.0.4
  services:
    - docker:28.0.4-dind
  # Do not download artifacts from previous stage
  dependencies: []
  before_script:
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
  script:
    - TAG=debug
    - *docker_build_args
    - |
      eval "docker build \
      --build-arg TAG=$TAG \
      $DOCKER_ARGS \
      -t $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME ."
    - docker push $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME