Image size

Minimize your image size not only enhance your develop speed, but also help for better scaling speed in container cluster (e.g. AWS ECS, Kubernetes)

Docker provide a feature called multi-stage build.

Your final image can based on a previous image to reduce the image layers, copying the artifact you really need.
This significantly help us to reduce the image size.

Here’s an example for Docker doc, compare these two Dockerfile.

  • Fat

    • Dockerfile

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      FROM golang:1.21
      WORKDIR /src
      COPY <<EOF ./main.go
      package main
      
      import "fmt"
      
      func main() {
        fmt.Println("hello, world")
      }
      EOF
      RUN go build -o /bin/hello ./main.go
      
      CMD ["/bin/hello"]
      
    • Image size total 841 MB

      IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
      de04cbb694be   10 minutes ago   CMD ["/bin/hello"]                              0B        buildkit.dockerfile.v0
      <missing>      10 minutes ago   RUN /bin/sh -c go build -o /bin/hello ./main…   27MB      buildkit.dockerfile.v0
      <missing>      10 minutes ago   COPY <<EOF ./main.go # buildkit                 78B       buildkit.dockerfile.v0
      <missing>      10 minutes ago   WORKDIR /src                                    0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     WORKDIR /go                                     0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     RUN /bin/sh -c mkdir -p "$GOPATH/src" "$GOPA…   0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     COPY /target/ / # buildkit                      214MB     buildkit.dockerfile.v0
      <missing>      41 hours ago     ENV PATH=/go/bin:/usr/local/go/bin:/usr/loca…   0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     ENV GOPATH=/go                                  0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     ENV GOTOOLCHAIN=local                           0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     ENV GOLANG_VERSION=1.21.11                      0B        buildkit.dockerfile.v0
      <missing>      41 hours ago     RUN /bin/sh -c set -eux;  apt-get update;  a…   258MB     buildkit.dockerfile.v0
      <missing>      2 days ago       /bin/sh -c set -eux;  apt-get update;  apt-g…   177MB
      <missing>      2 days ago       /bin/sh -c set -eux;  apt-get update;  apt-g…   48.4MB
      <missing>      2 days ago       /bin/sh -c #(nop)  CMD ["bash"]                 0B
      <missing>      2 days ago       /bin/sh -c #(nop) ADD file:b532f8e401e9a1fcc…   117MB
      
  • Thin

    • Dockerfile

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      FROM golang:1.21 as builder
      WORKDIR /src
      COPY <<EOF ./main.go
      package main
      
      import "fmt"
      
      func main() {
            fmt.Println("hello, world")
      }
      EOF
      RUN go build -o /bin/hello ./main.go
      
      FROM scratch
      COPY --from=builder /bin/hello /bin/hello
      CMD ["/bin/hello"]
      
    • Image size - Only 1.8 MB

      IMAGE          CREATED         CREATED BY                              SIZE      COMMENT
      ee1389c8966e   8 minutes ago   CMD ["/bin/hello"]                      0B        buildkit.dockerfile.v0
      <missing>      8 minutes ago   COPY /bin/hello /bin/hello # buildkit   1.8MB     buildkit.dockerfile.v0
      

Compare this two cases image size, that’s why it is important leverage multi-stage build to minimize your image size.