Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multistage builds with yum

Tags:

docker

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.

Option 1

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.

Option 2

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?

Option 3

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 ...
like image 625
Vorticity Avatar asked Apr 13 '18 20:04

Vorticity


People also ask

What is Docker multistage build?

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.

Can you have multiple Dockerfiles?

As Kingsley Uchnor said, you can have multiple Dockerfile , one per directory, which represent something you want to build.

Is this an advantage of multi-stage builds?

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.

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.


1 Answers

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.

like image 65
CanciuCostin Avatar answered Oct 31 '22 03:10

CanciuCostin