需要添加non_idempotent,官方文档的说明是: normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server (1.9.13); enabling this option explicitly allows retrying such requests; 意思是如果不加上non_idempotent,对POST这些不幂等的方法,出错是不会重试的。
CICD有很多方案,如Drone、Jenkins、Gitlab等,过往的经历告诉我,不能单纯为了Go而使用Go,除非Go编写的服务确实好用,足够成果。从简单实现的角度,通过Gitlab来完成,公司的部署环境有些特殊,有安全层面的考虑,是不能直接访问外网的,包括但不限于docker pull、go get、go mod download等等。如何加快CI的执行速度,如何使得构建后的镜像最小,减少传输带宽,如何复用Go相关的package,减少多次构建需要重新下载等等,就这些问题分享一下我的思路和做法。
若多个阶段使用同个镜像,那么多阶段构建等于压缩了中间多个层,将他们合并到一个层。如我们在git中add了一个较大的文件,然后下一次commit的时候把他删除了,虽然我们拉取这个git代码时,这个文件不在了,但是他一直存在在这个仓库,还是会占用较大的体积。所以我们做的ADD data ./和RUN rm ./data,其实就是个障眼法,掩耳盗铃,这个data还是存在于镜像中。所以可以在移除掉之后,通过多阶段构建,将结果COPY一份,不需要中间过程产生的文件等。
1 2 3 4 5 6 7
FROM golang:1.12 as build-env WORKDIR /go/src/y.cn/some ADD . ./ RUN CGO_ENABLED=0 GO111MODULE=on go build -ldflags -o some y.cn/some FROM golang:1.12 WORKDIR /go COPY --from=build-env /go/src/y.cn/some/some ./
FROM golang:1.12 as build-env WORKDIR /go/src/y.cn RUN git clone git@y.cn:some.git --depth 1 \ && cd some \ && CGO_ENABLED=0 GO111MODULE=on go build -ldflags -o some y.cn/some
Go Mod是Go新引入的一个包管理工具,实际上谈不上成熟,官方也没有推荐使用,但go mod毕竟还是未来,提前做好准备还是十分必要的。原先的GoVendor/GoDep的包管理,并未在部署上尝试特别大的问题。但由于go mod下载的package其实是放在你的$GOPATH/pkg/mod中,并没有加载到你的项目中,go mod vendor我执行之后也并未成果,暂时没找到什么原因。 所以使用go mod也带来一个挑战,事实上很多服务器的环境,并没有一个放开的公网网络,若 package之前未层使用过,go build或者go mod download的时候,都需要下载对应的package。意味着给Go项目的CICD、测试带来了一些影响。 在如何解决这类问题方面,分享一下我的看法,无非就是线上环境的$GOPATH/pkg/mod需要提前准备好相关package的问题。想到了可以通过golang:latest作为基础镜像,把项目git仓库ADD进去,go mod download下载所有所需的package,然后删掉git库,commit这个镜像到线上,那线上就有pkg/mod了。然后这个镜像就可以作为线上构建的基础镜像,包含所需的库,并且提供一些必备的工具脚本。
1 2 3 4 5 6 7 8 9 10 11
FROM golang:1.13 as build-env WORKDIR /go/src/y.cn/some COPY go.mod ./ RUN GO111MODULE=on go mod download FROM golang:1.13 WORKDIR /go RUN apt-get update && apt-get install -y mariadb-client > /dev/null RUN go get golang.org/x/tools/cmd/goimports \ && go get honnef.co/go/tools/cmd/staticcheck \ && go get github.com/golangci/golangci-lint/cmd/golangci-lint COPY --from=build-env /go/ ./