Search code examples
dockerdocker-builddocker-multi-stage-build

Docker: How to use multistage images after build finishes


Scenario

  • Multistage builds combine multiple Dockerfile sections into a single one
  • Intermediary and final stages can copy files from the upper stages
  • Final stage is suggested to have only the binaries needed.

With those in mind, I'd like to build the follow

FROM fat-base as build
RUN setup unit test frameworks
RUN setup integration test frameworks
RUN setup functional test frameworks
RUN setup all heavy lifting stuff
CMD test

FROM slim-base
COPY --from=build /runtime/binary /bin/binary
ENTRYPOINT /bin/binary

Reuse of Base Stage

  • Instead of running tests in the intermediary stages, I'd like to run them outside the image so that I can re-order the sequence of tests and add more switches at a Pipeline layer (Jenkins CI, Travis, etc)
  • I would like to be able to use the base image built.
  • As suggested for Testing stages, a secondary Dockerfile.test could be used. However, I'd like to maintain a single Dockerfile with all stages.

Here's an requirement to run

docker build -t my-binary .
docker run -ti my-binary[0] unit
docker run -ti my-binary[0] integration --all
docker run -ti my-binary[0] functional --only-label=container

Question

  • Is this currently supported?
  • Is there a workaround?

Solution

  • As explained in this page of the doc, you can use the --target option of docker build to create an image corresponding to an intermediate stage of the build.

    Using your Dockerfile, this would amount to the following commands:

    docker build --target build -t my-binary-test .
    docker build -t my-binary .
    docker run -ti my-binary-test # run "test" as specified by "CMD test"
    docker run -ti my-binary-test test unit
    docker run -ti my-binary-test test integration --all
    docker run -ti my-binary-test test functional --only-label=container
    

    Note that I prepended the test program name in the last three commands above because the last instruction CMD test of your build stage will actually be overwritten by all the arguments given at command line. To have more insight on the semantics of CMD and ENTRYPOINT directives, I suggest to read that section of the Dockerfile reference.

    Also, you may want to use the --rm option of docker run in order to automatically remove the created containers when they exit.