When you build your own docker image from Dockerfile each instruction in Dockerfile creates a new layer to your base image with its all dependencies so that even your very tiny application image size may be in 1GiB size and it is not desirable in the production environment to be such a big size due to the below reasons.
- Large Images takes longer to Download
- Large Images takes up more disk space
- Large Images contains unnecessary components
How to Reduce Image Size ?
Answer is multi-stage build. Multi-Stage builds enables you to create smaller container images with better caching and smaller security footprint. In this post, It will be shown you how to minimize your docker image step by step. For this experiment, It is written very simple Go web application. Let’s create a web application named main.go
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r \*http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path\[1:\])
log.Printf("connection from:%s",r.RemoteAddr)
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Creating a Dockerfile.
FROM golang:alpine AS builder
WORKDIR /webapps/app
ADD . /webapps/app
RUN go build -o main .
EXPOSE 8080
CMD ["/webapps/app/main"]
Building docker image
tesla@otuken:~/DockerTraining/SimpleHello$ sudo docker build -t gokay/goweb:1 .
As you see in the Figure-1 image size that simple application is 317MB.
Multi-Stage Build:
In this section, it will be shown you how to reduce the docker image size with Multi-Stage build. Only thing we need to do is adding some lines in our Dockerfile.
FROM golang:alpine AS builder
WORKDIR /webapps/app
ADD . /webapps/app
RUN go build -o main .
FROM alpine
WORKDIR /app
ADD . /app
COPY --from=builder /webapps/app/main /app
EXPOSE 8080
CMD ["/app/main"]
tesla@otuken:~/DockerTraining/SimpleHello$ sudo docker build -t gokay/goweb:1 .
After building our new image with new Dockerfile image size considerably reduced.
Image size 11MB As you see docker image size is now 11MB. If this size enough for you you can skip reading rest of the post. We can even reduce the image size a bit more as we write our application in Go. We can disable the cross-compilation as below.
FROM golang:alpine AS builder
WORKDIR /webapps/app
ADD . /webapps/app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
FROM alpine
WORKDIR /app
ADD . /app
COPY --from=builder /webapps/app/main /app
EXPOSE 8080
CMD ["/app/main"]
Want to Reduce More ?
You can use scratch image which is the minimalist image. But I would recommend to use alpine as it the security-oriented Linux distribution.
FROM golang:alpine AS builder
WORKDIR /webapps/app
ADD . /webapps/app
#RUN go build -o main .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
#EXPOSE 8080
#CMD ["/webapps/app/main"]
FROM scratch
WORKDIR /app
ADD . /app
COPY --from=builder /webapps/app/main /app
EXPOSE 8080
CMD ["/app/main"]
tesla@otuken:~/DockerTraining/SimpleHello$ sudo docker build -t gokay/goweb:1 .
Leave a Reply