go Dockerfile 编排

20 min read
FROM golang:1.14-alpine as builder
WORKDIR /usr/src/app
ENV GOPROXY=https://goproxy.cn
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
  apk add --no-cache upx ca-certificates tzdata
COPY ./go.mod ./
COPY ./go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o server &&\
  upx --best server -o _upx_server && \
  mv -f _upx_server server

FROM scratch as runner
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/src/app/server /opt/app/
CMD ["/opt/app/server"]
  • 选择 golang:1.14-alpine 作为编译环境,是因为这是体积最小的golang编译环境

  • 设置 GOPROXY 是为了提升构建速度

  • 先复制 go.modgo.sum ,然后 go mod download,是为了防止每次构建都会重新下载依赖包,利用docker构建缓存提升构建速度

  • go build 时加上 -ldflags "-s -w" 去除构建包的调试信息,减小go构建后程序体积,大概能减小 1/4

  • 使用了多阶段构建,也就是 FROM XXX as xxx ,在构建程序包的时候,使用带编译环境的镜像去构建,运行的时候其实完全不需要go的编译环境,所以在运行阶段使用docker的空镜像 scratch 去运行。这部是减小镜像体积最有效的方法了。

  • COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 解决时区问题