Go Docker 镜像进阶: 精简镜像

Go Docker 镜像进阶: 精简镜像

​[图片来自 https://www.facebook.com/sequenceprocess/]

问题: 入门到生产级的差距

昨天的文章《为 Go 应用创建 Docker 镜像》, 算是入门级的, 并不适用于生产级. 为什么?

$ docker images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
addozhang/golang-hello-world                  latest              4cce1292a87a        4 seconds ago       813MB

整个镜像的大小有 813MB, 这还只有一个简单的 Hello world. 因为其中包含了 Golang 的编译和运行环境. 但是实际生产环境中, 我们并不需要这么多.

先看结果

精简之后只有 2.07MB, 而且并不影响运行.

$ docker images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
addozhang/golang-hello-world                  latest              4cce1292a87a        3 minutes ago       813MB
addozhang/golang-hello-world2                 latest              1da5bb994074        7 minutes ago       2.07MB

$ docker run --rm addozhang/golang-hello-world2
Hello world

解决方案

如果做到的? 首先从基础镜像开始, 换成scratch1. 构建时将编译好的文件复制到镜像中

FROM scratch
ADD golang-hello-world /
CMD ["/golang-hello-world"]

假如你是使用go build来编译, 在 Macos 上会遇到如下问题:

$ docker run --rm addozhang/golang-hello-world2
standard_init_linux.go:211: exec user process caused "exec format error"

解决方案是CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

从头来看, 构建出一个精简的镜像, 我们需要:

  1. 运行CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build构建 linux 环境的可执行文件. 该文件并不能在 mac 上运行
  2. 使用docker build进行构建

这样的操作步骤太麻烦, 还能不能精简一下?

进阶: 使用 Docker 的多步构建

#build stage
FROM golang as builder

ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io

WORKDIR /app

COPY go.mod .
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

#image stage
FROM scratch
COPY --from=builder /app/golang-hello-world /
CMD ["/golang-hello-world"]

参考

https://dev.to/plutov/docker-and-go-modules-3kkn


  1. scratch是一个空的镜像文件 ↩︎

(转载本站文章请注明作者和出处乱世浮生,请勿用于任何商业用途)

comments powered by Disqus