我本来只想看看docker官方提供的CI/CD教程,然后官方引用了,Ben's blog提到了CI/CD的最佳实践,然后我就去阅读了大神的博客,然后大神引用了另一个大神的通过docker开发你的Go程序的系列文章。OK,我还挺喜欢这种引用的,那一层一层看吧,肯定都是好内容。
Chris大神说他刚开始加入开发团队的时候,也遇到了很多编程语言,配置开发环境的问题,经常需要问同事帮忙,还经常被各种工具困扰,这些过程非常花费时间,并且他在维护debug CI过程的时候也非常痛苦。
他提到了一个角度我觉得很好,他说Go开发的工具链,提供快速编译时间,内置依赖管理,简单的交叉编译。但工具链会遇到诸多Go版本不匹配,缺少依赖,配置不同的问题。一个很好的例子就是在许多项目中使用了gRPC,因此特定版本的protoc也很重要。
大神的博客涵盖了构建,测试,CI和优化方案帮助大家更快上手。
迎接究极干货
从简单的go程序开始:
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
通过go build就可以编译成二进制文件。
go build -o bin/example .
外加简单的Dockerfile
FROM golang:1.14.3-alpine As build
WORKDIR /src
COPY . .
RUN go build -o /out/example .
FROM scratch AS bin
COPY --from=build /out/example /
说简单也不简单,两阶段构建,第一阶段,构建,用了Go Alpine镜像,Alpine镜像大家了解吧,很多语言都有这个版本,超级轻量化,常规机遇Debian的Golang轻量镜像代替品。定义了go的版本(我这个时候还在想,要不要做一个新版本的用例)。设置了工作目录,将代码复制到容器中,然后编译。第二阶段使用了临时的空镜像(这个我头次见)然后将第一阶段的编译好的耳机只文件复制到文件系统中。大神贴心的提到,如果我们的程序需要一些其他的资源比如CA证书,这些也需要包含在最终的镜像中。
小tips:
我之前使用Alpine镜像的时候,我们是不用跑docker run -it < image_id > bash的,因为Alpine不带,那怎么进一个CLI呢?可以用/bin/sh。
升级版(交叉编译版)
FROM --platform=${BUILDPLATFORM} golang:1.14.3-alpine AS build
WORKDIR /src
ENV CGO_ENABLED=0
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /out/example .
FROM scratch AS bin
COPY --from=build /out/example /
使用了BUILDPLATFORM设置基础镜像平台。使用TARGETOS和TARGETARCH告诉Go在那个平台构建。
大神还提供了Makefile,makfile我还没有学过多语法,一起看看吧
all: bin/example
.PHONY: bin/example
bin/example:
@docker build . --target bin --output bin/ --platform local
使用make,或者make bin/example都能构建。
再进一步
FROM --platform=${BUILDPLATFORM} golang:1.14.3-alpine AS build
WORKDIR /src
ENV CGO_ENABLED=0
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /out/example .
FROM scratch AS bin-unix
COPY --from=build /out/example /
FROM bin-unix AS bin-linux
FROM bin-unix AS bin-darwin
FROM scratch AS bin-windows
COPY --from=build /out/example /example.exe
FROM bin-${TARGETOS} AS bin
这已经多阶段方案了吧,Linux(bin-linux),macOS(bin-darwin),windows(bin-windows)。我的天真希望我不要遇到这些问题。这些可以让我动态选择编译目标。
然后再优化Makefile
all: bin/example
PLATFORM=local
.PHONY: bin/example
bin/example:
@docker build . --target bin --output bin/ --platform ${PLATFORM}
然后我们就可以指定使用平台了
make PLATFORM=windows/amd64
makefile俩面的参数能这么直接传真实学到了
还能学到一点
大神提到了使用.dcokerignore减少不需要的内容,如果我们的项目通过git进行代码管理,我觉得大多数的项目都是git管理吧,我们可以排出.git/目录, 这一点再docker官网的教程了都没写。
reference
本文所有的例子都来自于大神的博客: https://www.docker.com/blog/containerize-your-go-developer-environment-part-1/
网友评论