How to flatten a Docker image?

前端 未结 3 1232
温柔的废话
温柔的废话 2020-12-02 11:04

I made a Docker container which is fairly large. When I commit the container to create an image, the image is about 7.8 GB big. But when I export the container

3条回答
  •  一整个雨季
    2020-12-02 12:00

    Now that Docker has released the multi-stage builds in 17.05, you can reformat your build to look like this:

    FROM buildimage as build
    # your existing build steps here
    FROM scratch
    COPY --from=build / /
    CMD ["/your/start/script"]
    

    The result will be your build environment layers are cached on the build server, but only a flattened copy will exist in the resulting image that you tag and push.


    Note, you would typically reformulate this to have a complex build environment and only copy over a few directories. Here's an example with Go to make a single binary image from source code and a single build command without installing Go on the host and compiling outside of docker:

    $ cat Dockerfile 
    ARG GOLANG_VER=1.8
    FROM golang:${GOLANG_VER} as builder
    WORKDIR /go/src/app
    COPY . .
    RUN go-wrapper download 
    RUN go-wrapper install
    
    FROM scratch
    COPY --from=builder /go/bin/app /app
    CMD ["/app"]
    

    The go file is a simple hello world:

    $ cat hello.go 
    package main
    
    import "fmt"
    
    func main() {
            fmt.Printf("Hello, world.\n")
    }
    

    The build creates both environments, the build environment and the scratch one, and then tags the scratch one:

    $ docker build -t test-multi-hello .                                                                                                                              
    Sending build context to Docker daemon  4.096kB
    Step 1/9 : ARG GOLANG_VER=1.8
     ---> 
    Step 2/9 : FROM golang:${GOLANG_VER} as builder
     ---> a0c61f0b0796
    Step 3/9 : WORKDIR /go/src/app
     ---> Using cache
     ---> af5177aae437
    Step 4/9 : COPY . .
     ---> Using cache
     ---> 976490d44468
    Step 5/9 : RUN go-wrapper download
     ---> Using cache
     ---> e31ac3ce83c3
    Step 6/9 : RUN go-wrapper install
     ---> Using cache
     ---> 2630f482fe78
    Step 7/9 : FROM scratch
     ---> 
    Step 8/9 : COPY --from=builder /go/bin/app /app
     ---> Using cache
     ---> 5645db256412
    Step 9/9 : CMD /app
     ---> Using cache
     ---> 8d428d6f7113
    Successfully built 8d428d6f7113
    Successfully tagged test-multi-hello:latest
    

    Looking at the images, only the single binary is in the image being shipped, while the build environment is over 700MB:

    $ docker images | grep 2630f482fe78
                                  2630f482fe78        6 days ago          700MB
    
    $ docker images | grep 8d428d6f7113
    test-multi-hello      latest              8d428d6f7113        6 days ago          1.56MB
    

    And yes, it runs:

    $ docker run --rm test-multi-hello 
    Hello, world.
    

提交回复
热议问题