Advanced multi-stage build templates

 3r33338. 3r3-31. 3r3333317. Advanced multi-stage build templates
3r33333.  3r33338. 3r3333317. The multistage assembly feature in Dockerfile files allows you to create small images of containers with a higher level of caching and a smaller amount of protection. In this article, I’ll show several advanced templates — something more than copying files between build and execute steps. They allow you to maximize the effectiveness of the function. However, if you are a beginner in the area of ​​multi-stage assembly, then first, probably, it will not be superfluous to read r3r38. 3r3325 usage guide .
3r311.
3r33333.  3r33338.
Compatible versions 3r33232. 3r33333.  3r33338. 3r3333317. Support for multi-stage build was added to Docker in version v???. All templates work with any subsequent version, but some are much more efficient, thanks to using the server part 3r320. BuildKit
to linkers. For example, BuildKit effectively skips unused stages and, if possible, creates stages at the same time (I singled out these examples separately). Currently BuildKit is added to Moby as an experimental server part of the assembly and should be available in Docker CE v???. It can also be used stand alone 3r3325. or as part of the 3-33326 project. img .
3r33333.  3r33338.
3r33333.  3r33338. 3r3334. Inheritance from step 3r3335. 3r33333.  3r33338. 3r3333317. Multi-stage build adds several new syntax concepts. First of all, you can assign a step starting with the command 3r3309. FROM , name AS stagename and use option 3r3309. --from = stagename in team 3r3309. COPY to copy files from this stage. Actually team 3r3309. FROM and label 3r3309. --from have much more in common, not for nothing that they have the same name. Both take the same argument, recognize it and either start a new stage from this point, or use it as a source to copy the file. That is, to use the previous stage in the original image quality for the current stage, you can take not only 3r3309. --from = stagename , but also the name of the stage FROM stagename . It is useful if you use the same common parts in several commands in the Dockerfile: reduces the common code and simplifies its maintenance, keeping the child stages separate. Thus, rebuilding one stage does not affect the build cache for others. Accordingly, each stage can be assembled individually with the help of the label 3r3309. --target when calling 3r3309. docker build . 3r33333.  3r33338.
    FROM ubuntu AS base
RUN apt-get update && apt-get install git
FROM base AS src1
RUN git clone
FROM base as src2
RUN git clone
3r3305. 3r33333.  3r33338. 3r3333317. In this example, the second and third stages in BuildKit are built simultaneously. 3r33333.  3r33338.

Direct use of images

3r33333.  3r33338. 3r3333317. Instead of using assembly step names in commands 3r3309. FROM , which previously only supported links to images, you can directly use images - using the 3r3-3309 label. --from . It turns out to copy files directly from these images. For example, 3r3309. linuxkit /ca-certificatesimage The following code directly copies the TLS CA roots into the current stage. 3r33333.  3r33338.
    FROM alpine
COPY --from = linuxkit /ca-certificates //
3r3305. 3r33333.  3r33338.

Generic Image Alias ​​

3r33333.  3r33338. 3r3333317. The build step does not necessarily include any commands; it may consist of a single line FROM . If an image is used in several places, it will make reading easier and make it so that if you need to update a shared image, you only need to change one line. 3r33333.  3r33338.
    FROM alpine: 3.6 AS alpine
FROM alpine
RUN
FROM alpine
RUN
3r3305. 3r33333.  3r33338. 3r3333317. In this example, every place that uses the alpine image is actually fixed at alpine: 3.6 r3r3310. , not 3r3309. alpine: latest . When it comes time to upgrade to alpine: ???r3r3310. , you will need to change a single line, and there is no doubt: now the updated version is used in all elements of the assembly. 3r33333.  3r33338. 3r3333317. This is all the more important when the assembly argument is used in the alias. The following example is similar to the previous one, but allows the user to override all instances of the assembly that have an alpine image involved, by setting the option --build-arg ALPINE_VERSION = value . Remember: any arguments used in commands FROM , you need to define 3r3133. before the first stage of assembly . 3r33333.  3r33338.
    ARG ALPINE_VERSION = ???r3333338. FROM alpine: $ {ALPINE_VERSION} AS alpine
FROM alpine
RUN
3r3305. 3r33333.  3r33338. 3r3147. Using assembly arguments in "- from" 3r33333.  3r33338. 3r3333317. The value indicated in the label is --from teams 3r3309. COPY
, must not contain assembly arguments. For example, the following example is invalid. 3r33333.  3r33338.
    //THIS EXAMPLE IS INTENTIONALLY INVALID
FROM alpine AS build-stage0
RUN
FROM alpine
ARG src = stage0
COPY --from = build - $ {src}. .
3r3305. 3r33333.  3r33338. 3r3333317. This is due to the fact that the dependencies between the stages need to be determined even before the assembly begins. Then the constant evaluation of all teams is not required. For example, the environment variable defined in image alpine may affect the estimated value of --from . The reason why we can evaluate the arguments of the command FROM , - that these arguments are defined globally before the start of any stage. Fortunately, as we found out earlier, it is enough to define the stage of the pseudonym with the help of one command 3r3309. FROM and refer to it. 3r33333.  3r33338.
    ARG src = stage0
FROM alpine AS build-stage0
RUN
FROM build - $ {src} AS copy-src
FROM alpine
COPY --from = copy-src. .
3r3305. 3r33333.  3r33338. 3r3333317. Now, if you override the assembly argument src , the initial stage for the final element 3r3309. COPY will switch. Note: if some stages are no longer used, then only BuildKit-based linkers will be able to skip them. 3r33333.  3r33338.

Conditions using build arguments

3r33333.  3r33338. 3r3333317. We were asked to add support for the style conditions in the Dockerfile. IF /ELSE . We still do not know whether we will add something similar, but in the future we will try - using the support of the client part in BuildKit. Meanwhile, to achieve a similar behavior, you can use the current multi-stage concept (with some planning). 3r33333.  3r33338.
    //THIS EXAMPLE IS INTENTIONALLY INVALID
FROM alpine
RUN
ARG BUILD_VERSION = 1
IF $ BUILD_VERSION == 1
RUN touch version1
ELSE IF $ BUILD_VERSION == 2
RUN touch version2
DONE
RUN
3r3305. 3r33333.  3r33338. 3r3333317. The previous example shows pseudo-code for recording conditions using IF /ELSE . To achieve similar behavior with the current multi-stage builds, you may need to define different branch conditions as separate steps and use an argument to choose the right dependency path. 3r33333.  3r33338.
    ARG BUILD_VERSION = 1
FROM alpine AS base
RUN
FROM base AS branch-version-1
RUN touch version1
FROM base AS branch-version-2
RUN touch version2
FROM branch-version - $ {BUILD_VERSION} AS after-condition
FROM after-condition
RUN
3r3305. 3r33333.  3r33338. 3r3333317. The last stage in the Dockerfile is based on the stage. after-condition which is an image alias (recognized on the basis of the build argument 3r3309. BUILD_VERSION ). Depending on the value of 3r3309. BUILD_VERSION choose one or another stage of the middle section. 3r33333.  3r33338. 3r3333317. Please note: only BuildKit-based linkers can skip unused branches. In previous versions of linkers, all stages would be built, but before creating the final image, their results would be discarded. 3r33333.  3r33338.

Development Assistant /Testing for the minimum production stage 3r326262. 3r33333.  3r33338. 3r3333317. Finally, let's take a look at an example of combining previous templates to demonstrate how to create a Dockerfile that creates a minimal production image and can then use its contents to test and create a development image. Let's start with the basic Dockerfile example: 3r33333.  3r33338.

    FROM golang: alpine AS stage0
FROM golang: alpine AS stage1
FROM scratch
COPY --from = stage0 /binary0 /bin
COPY --from = stage1 /binary1 /bin
3r3305. 3r33333.  3r33338. 3r3333317. When a minimal production image is created, this is a fairly common option. But what if you also need to get an alternative developer image or run tests with these binaries at the final stage? The first thing that comes to mind is simply to copy similar binaries during the testing and development phases. The problem is this: there is no guarantee that you will test all production binaries in the same combination. At the final stage, something may change, and you will forget to make similar changes at other stages or make an error in the path to copy binary files. In the end, we are not testing a separate binary file, but a final image. 3r33333.  3r33338. 3r3333317. An alternative is to define the development and testing phase after the production phase and copy the entire contents of the production phase. Then use for the production phase one team 3r3309. FROM to again make the default production phase the final step. 3r33333.  3r33338.
    FROM golang: alpine AS stage0
FROM scratch AS release
COPY --from = stage0 /binary0 /bin
COPY --from = stage1 /binary1 /bin
FROM golang: alpine AS dev-env
COPY --from = release //
ENTRYPOINT["ash"]3r33338. FROM golang: alpine AS test
COPY --from = release //
RUN go test
FROM release
3r3305. 3r33333.  3r33338. 3r3333317. By default, this Dockerfile will continue to build the default minimum image, while, for example, the build with the option. --target = dev-env will create an image with a shell containing all the binaries of the final version.
3r33333.  3r33338.
3r33333.  3r33338. 3r3333317. I hope this was useful and suggested how to create more efficient multistage Dockerfile files. If you participate in DockerCon2018 and want to learn more about multistep builds, Dockerfiles, BuildKit, or related topics, subscribe to the linker Hallway track or keep track of Docker’s internal meetings on tracks 3r3322. Contribute and Collaborate
or
Black Belt 3r3325. .
3r33338. 3r33338. 3r33338.
3r33338.
3r33338. 3r33338. 3r33338. 3r33338.
+ 0 -

Add comment