Dockerfile: how to create a new image from the last layer of another image

I do not fully understand the official guide "Use a previous stage as a new stage" at Use multi-stage builds.

There, the example is:

FROM golang:1.7.3
WORKDIR /go/src/
RUN go get -d -v
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/ .
CMD ["./app"] 

In my case, I want to take the last layer, that would be RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . in the example, as the only thing to keep. Is it true that I can drop all of the previous layers, meaning, does the last layer hold all of what I need? And how would I take over the last layer, then? In the example, I need to choose a folder /go/src/ in the first image --from=0 ("FROM namespace"), and I copy this to the build context of the second image .. But how do I know that folder, or what needs to be copied to run a fully working container on it? I expected to be able to copy a layer, not a folder.

I try this idea to get a smaller and secure second image:

  • to get rid of a private key that is used in a previous layer, following the advice of Using SSH keys inside docker container + comments;
  • and also, because my image is far too huge if I kept all of the "build data" in it.

The answer does not need to stick to the example Dockerfile.

EDITED after first answer:

I need to know the directories that I want to take over to the next image. And that is quite difficult, having installed many Python packages and ROS, which touch quite a few directories, not just the git project directory. And I need to copy the .bashrc. Is it right that I have to copy all of this by choice, and would it be interesting to copy just all? Since I am not sure whether the "build data" is saved in the directories at all, perhaps it is just in the layers? And if copying just all is the trick, how would I do that, just by

COPY --from=0 . .

perhaps?

1 Answer

When you say

COPY --from=something /source /target

You change the context of that copy from your build context to another image. In the above case the image is something, that could be an image name, a stage number, or the the previous stage could name it's stage name with FROM base as something and then the result of that stage would be known as something.

With that change in context, you are copying specific files, /source from that context, to /target as a new layer in your resulting image. Nothing else is copied, including none of the build history of the earlier stages, and no other files from the filesystem.

However, if something is an external image that you need to pull from a registry, that entire image needs to be pulled to find /source in that image, which could be spread across multiple layers.

This is one of several ways to inject credentials. However realize that the build host will have these credentials stored as layers for the earlier stages that you hopefully do not push. Other options to inject credentials include not doing it in the build at all (pull the git repos before running the build), or using buildkit's --mount syntax.

5

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like