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
解决方案
如果做到的? 首先从基础镜像开始, 换成scratch
1. 构建时将编译好的文件复制到镜像中
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
从头来看, 构建出一个精简的镜像, 我们需要:
- 运行
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
构建 linux 环境的可执行文件. 该文件并不能在 mac 上运行 - 使用
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
-
scratch
是一个空的镜像文件 ↩︎