0

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/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
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/github.com/alexellis/href-counter/app .
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/github.com/alexellis/href-counter/app 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?

Code answer from the questioner

Here is the code that I made from the answer below:

Using SSH keys inside docker container

1 Answer 1

1

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
  • 1
    @questionto42 if your previous stage scatters files all over the filesystem, that's likely from an installer that modifies it's behavior based on what's already on the filesystem, and not a good use case for multi-stage builds. Multi-stage builds move the external process of building an artifact like a jar, and move it into the docker build to be repeatable in different environments, allowing you to ship an image without the compiler. Interpreted languages like Python don't fit that model.
    – BMitch
    Commented Mar 22, 2021 at 12:11
  • 1
    (the above is responding to a now deleted comment, but I'm leaving it since I think it provides some useful additional context)
    – BMitch
    Commented Mar 22, 2021 at 12:12
  • I see, then it is clear why I could not understand the official guide. It might only apply when I first downloaded the git repo, before installing anything else, and copied the full git project folder over to a second image, without the private key. Your answer is helping me, not so much regarding the image size since git and openssh are not that large, but regarding the private key problem. (I deleted the first comment since I need to talk to you over the question as much as possible, I added it there.) Commented Mar 22, 2021 at 12:14
  • I have just looked it up using docker history --no-trunc <Image ID>: RUN /bin/sh -c apt-get -yqq install openssh-client causes almost 1 GB of image space, that is not as little as thought, thus your answer also helps reducing the size of a second image when leaving git and ssh programs aside. Commented Mar 22, 2021 at 12:33
  • It works. It only saved me 0.02 GB of image size, though, from 6.2GB down to 6.18GB :), probably, because my second image installed git again in its base image or in one of the two "full" installers. Anyway, the private key is not in the image anymore. I used the "alpine" base image for cloning the git repo, see the result at Using SSH keys inside docker container. Commented Mar 22, 2021 at 15:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .