I'm struggling with converting my current dockerfiles to multistage builds to cut out some cruft. I start from a base image, install a bunch of stuff via yum along with a bunch of other packages that I install from source.
At this point, I would like to start with a fresh image and bring in only the packages installed via yum and the binaries from my installations from source. I see three ways to do this, but I don't like the first option and don't know how to do the other two.
Build a separate Dockerfile for the yum install, then use that as my base image prior to the installations from source.
I don't like this option because it adds more to my build workflow. It would be nice to have everything contained in one Dockerfile. Maybe this is the way I need to go, though.
Install packages via yum in a different directory and copy across to the next stage of the build.
I have found that I can install packages in a non-default directory via yum install --installroot=/foo --releasever=/ packagename
, however, this installs all requirements to /foo rather than continuing to use packages installed in /usr, causing the image to grow significantly.
Is there a way to install packages via yum in a different directory, but have it continue to resolve its dependencies from the default directory?
Install packages via yum, then start the next build stage from the point after the yum packages have been installed.
Is there a way to use the layer resulting from a build stage as the start of the next build stage? Something like this:
FROM centos7 as first
RUN some stuff
FROM first as second
RUN some stuff
FROM second
COPY --from=second ...
A multistage Docker build is a process to create a Docker image through a series of steps. Each stage accomplishes a task -- such as to load or remove build tools -- specific to the base Docker image, as part of the compilation process.
As Kingsley Uchnor said, you can have multiple Dockerfile , one per directory, which represent something you want to build.
Multi-stage builds can help to share intermediate image layers with your team. You'll need to tag them right, and make sure to push them. It can pay off though! Pullable intermediate images can help to make the first developer experience more pleasant.
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.
Use multi-stage builds
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. To show how this works, consider this example:
Dockerfile
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"]
You only need the single Dockerfile. You don’t need a separate build script, either. Just run docker build.
$ docker build -t alexellis2/href-counter:latest .
The end result is the tiny production image, with a significant reduction in complexity. You don’t need to create any intermediate images and you don’t need to extract any artifacts to your local system at all.
How does it work?
The second FROM instruction starts a new build stage with the alpine:latest image as its base. The COPY --from=0 line copies just the built artifact from the previous stage into this new stage. The Go SDK and any intermediate artifacts are left behind, and not saved in the final image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With