12

Thanks to Docker multi-stage builds, we can compile some artefacts in one environment and put them for execution in other one.

As result, there are two images, where the final corresponding to the last stage and provided tag gets tagged as defined; there is no tag for intermediate (ones), but they remain there as well.

Question: is it possible to create a series of tagged images for all defined stages using multi stage build out of one Dockerfile?

1

2 Answers 2

15

You can build and tag any stage of a multi-stage build. Just use the --target option to docker build. E.g.

docker build --target jdk -t myapp-jdk:v1 .
docker build --target jre -t myapp:v1 .

With the layer caching, the the earlier steps will be reused from the cache and not rerun from scratch each time, so there's little downside to running the build to different targets multiple times.

If you absolutely need to run this from a single build command, you can parse the output of the build, get the image id of the intermediate step, and tag that image id:

docker tag <some_image_id> myapp-jdk:v1
3
  • One reason to try to do this in a single command: the build context doesn't need to be pulled together more than one time.
    – seveibar
    Aug 25, 2018 at 11:15
  • 1
    @seveibar Good point. Buildkit will handle that much better by only sending any changes in the build context, but that's still in experimental right now.
    – BMitch
    Aug 25, 2018 at 11:23
  • The developers are looking into better ways to handle this with buildkit. This issue would be good to follow: github.com/moby/moby/issues/38197#issuecomment-438348158
    – BMitch
    Feb 15, 2019 at 1:30
1

I stumbled upon a solution which I thought was quite elegant, and only requires you to build once:

Use LABEL feature in your multistage builds, and then after building, you can tag based on label.

Advantages:

  • only pull together the build context once
  • fast command to tag after the build has been done

The example was discussed in https://forums.docker.com/t/tag-intermediate-build-stages-multi-stage-build/34795

Using the LABEL command in my dockerfile I added a label to the build stage I’m interested in, then filter for it later:

FROM node as builder-stage
LABEL builder=true

FROM node as app-stage
LABEL builder=false

Now to filter, sort newest first, cut out the date, and take the top row:

docker images --filter “label=builder=true” --format ‘{{.CreatedAt}}\t{{.ID}}’ | sort -nr | head -n 1 | cut -f2

Note that it is important to remove the label in the next build stage.

This approach works really well for me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.