Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?
like image 702
Marcello de Sales Avatar asked Apr 15 '18 16:04

Marcello de Sales


People also ask

Where do Docker images go after build?

If you use the default storage driver overlay2, then your Docker images are stored in /var/lib/docker/overlay2 . There, you can find different files that represent read-only layers of a Docker image and a layer on top of it that contains your changes.

How do multistage Docker builds work?

With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don't want in the final image.

How do I use multiple images in Dockerfile?

Use of two commands – FROM and AS, in particular, allows you to create a multi-stage dockerfile. It allows you to create multiple image layers on top of the previous layers and the AS command provides a virtual name to the intermediate image layer. The last FROM command in the dockerfile creates the actual final image.

Why use multi-stage builds?

A multistage build allows you to use multiple images to build a final product. In a multistage build, you have a single Dockerfile, but can define multiple images inside it to help build the final image.


1 Answers

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.

like image 61
ErikMD Avatar answered Oct 17 '22 10:10

ErikMD