go build docker 打包压缩到最小镜像

2020-09-06
build
docker
go
golang

直接上 demo 代码

 1FROM golang:alpine as builder
 2WORKDIR /app
 3COPY . /app
 4RUN set -x \
 5    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
 6    && apk update \
 7    && apk --no-cache add tzdata upx \
 8    && go env -w GO111MODULE=on \
 9    && go env -w GOPROXY=https://goproxy.cn,direct \
10    && go env -w CGO_ENABLED=0 \
11    && go env -w GOOS=linux
12RUN set -x \
13    && go build -ldflags "-s -w" -o server_temp \
14    && upx -9 server_temp -o server \
15    && rm -f server_temp
16FROM scratch as production
17COPY --from=builder /app/server .
18COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
19EXPOSE 8080
20CMD ["/server"]

详细说明

  1. 分为构建和应用两部分,分开的后,最终实际只用到了构建的成品,所有构建前的源码以及构建过程产生的缓存包,还有构建环境其实都没有大的作用,docker 本身就用 go 写的,所有有个特性,可以直接打成 docker 底层包放到 docker 空镜像里使用。
  2. 国内源, go mod 就不多说了
1sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
1go env -w GO111MODULE=on \
2go env -w GOPROXY=https://goproxy.cn,direct \
  1. 打包方式
    关闭 cgo,默认 cgo 为开启状态(1),在 cgo 开启状态下允许你在 Go 代码中调用 C 代码,go 部分包中有 c 语言的实现,开启状态下可能会有动态引用外部。具体可以看 go 的可移植性和 c 的比较
1go env -w CGO_ENABLED=0

GOOS 为 linux,可以指定编译的环境,可根据情况填写

1GOOS=linux
  1. 编译,添加编译参数 -ldflags "-s -w" ,如果用变量加个-X,设置如下
1go build -ldflags "-s -w" -o server_temp

关于-ldflags 说明

1-w 去掉DWARF调试信息,得到的程序就不能用gdb调试了。
2-s 去掉符号表,panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果,
3-X 设置包中的变量值
  1. 借助第三方工具再压缩 upx, upx 后面压缩值为-1~-9,1 压缩速度最快,9 压缩最小
1upx -9 server_temp -o server
阅读 0