Is there a way to combine Docker images into 1 container?

David picture David · Sep 21, 2016 · Viewed 73.2k times · Source

I have a few Dockerfiles right now.

One is for Cassandra 3.5, and it is FROM cassandra:3.5

I also have a Dockerfile for Kafka, but t is quite a bit more complex. It is FROM java:openjdk-8-fre and it runs a long command to install Kafka and Zookeeper.

Finally, I have an application written in Scala that uses SBT.

For that Dockerfile, it is FROM broadinstitute/scala-baseimage, which gets me Java 8, Scala 2.11.7, and STB 0.13.9, which are what I need.

Perhaps, I don't understand how Docker works, but my Scala program has Cassandra and Kafka as dependencies and for development purposes, I want others to be able to simply clone my repo with the Dockerfile and then be able to build it with Cassandra, Kafka, Scala, Java and SBT all baked in so that they can just compile the source. I'm having a lot of issues with this though.

How do I combine these Dockerfiles? How do I simply make an environment with those things baked in?

Answer

Mohammed Noureldin picture Mohammed Noureldin · Jan 6, 2018

You can, with the multi-stage builds feature introduced in Docker 1.17

Take a look at this:

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"]  

Then build the image normally:

docker build -t alexellis2/href-counter:latest

From : https://docs.docker.com/develop/develop-images/multistage-build/

The end result is the same tiny production image as before, 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.