玖叶教程网

前端编程开发入门

教你使用go docker打包效率整整提升3倍,jenkins流水线打包不求人

最近研究了一下gin-vue-admin框架,其中官方自带docker镜像打包。我们在jenkins流水线将后端服务打包镜像上次到K8s 平台中,发现每次打包docker镜像构建时间需要花费1分半左右。这样打包构建速度非常耽误工作。jenkins流水线打包时间如下图:

从以上图可以看出**生成镜像**最浪费时间。我们在分析一下这个步骤到底花费了哪些时间

镜像开始打包,接下来有一段下载第三方依赖包

下载完成后发现花费了 42.2秒,好家伙大概镜像构建 一半以上的时间都浪费在下载第三方GO的依赖包。我们检查一下它dockerfile看看里面到底干了哪些事情。

FROM golang:alpine as builder

WORKDIR /go/src/ahzz/gin-vue-admin
COPY . .
WORKDIR /go/src/ahzz/gin-vue-admin/server
RUN ls
RUN pwd
RUN go env -w GO111MODULE=on \
    && go env -w GOPROXY=https://goproxy.cn,direct \
    && go env -w CGO_ENABLED=0 \
    && go env \
    && go mod tidy \
    && go build -gcflags "all=-N -l" -o server .

FROM alpine:latest

LABEL MAINTAINER="wwwzhouhui"

WORKDIR /go/src/ahzz/gin-vue-admin

COPY --from=0 /go/src/ahzz/gin-vue-admin/server ./
COPY --from=0 /go/src/ahzz/gin-vue-admin/server/resource ./resource/
COPY --from=0 /go/src/ahzz/gin-vue-admin/server/config.yaml ./
COPY --from=0 /go/src/ahzz/gin-vue-admin/server/dongtai-go-agent-config.yaml ./

EXPOSE 8080
ENTRYPOINT ./server

我们从上面dockerfile里面可以看出,镜像采用了分层打包模式,第一步在镜像里面 使用go mod tidy 镜像build.第二步在

alpine镜像中复制打包好的二进制文件和需要运行配置文件。我们知道第二步文件的复制+设置启动端口这个不需要花费多少时间,那么时间应该是消费在go build 中。我们知道go mod tidy 第一次运行的时候需要从远程服务器上面下载第三依赖的GO语言包。第二次运行go mod tidy 本地电脑或者服务器有第三方依赖包了,程序打包二进制文件这时间是非常短的。问题就在docker build 的时候每次单独的镜像都需要go mod tidy 需要下载第三方依赖包,而我们刚才分析了每次下载时间都消耗在40秒中。目前公司的项目都是基于docker镜像打包,依赖jenkins流水线打包,而且每天几百次构建,每次构建都浪费40秒中一年下来 在打包上耽误的时间是惊人 的。所以接下来我们需要改造打包模式,看看能不能提高打包镜像的效率。

公司现有环境思考:

3台jenkins 集群环境

13台rancher 集群环境(开发环境)

我们知道既然go mod tidy 第一次需要下载第三方依赖GO语言的包,那么我们可不可以把go build 放在jenkins中打包,打包好后的二进制文件 在复制到docker镜像中作为制品,这样就省下了每次go mod tidy 的时间了。思路是对的接下来我们就按照想法来改造dockerfile 和Jenkinsfile 文件。

第一步 三台jenkins 服务器上安装 go 运行环境(这个比较简单这里面就不做介绍了)

我们运行 go env

以上确保go 环境是OK的。

第二步:修改Jenkinsfile 代码。这里面我们需要在 编译程序增加相应的修改

tage('编译程序') {
            when {
                expression { deploy == true || deploy == 'true' }
            }
            steps {
                script {
                        def projectName = "${projectName}"
                        echo "项目容器名称:${projectName}"
                        //docker等相关配置文件拷贝到target下
                         copyConfigToTarget(projectName)
                         // 复制go 代码到target/settings 目录下
                         sh "cp -rf ${WORKSPACE}/server/  ${WORKSPACE}/target/settings/server/ "
                         sh """
                               cd ${WORKSPACE}/target/settings/server/
                               go env -w GO111MODULE=on
                               go env -w GOPROXY=https://goproxy.cn
                               go env -w CGO_ENABLED=0
                               go env
                               go mod tidy
                               go build -gcflags "all=-N -l" -o server .
                               cp ${WORKSPACE}/target/settings/Dockerfile ${WORKSPACE}/target/settings/server
                            """
                         echo " go build  完成"
                }
            }
        }

简单解释一下,上面主要作用就是把之前dockerfile 第一步放到Jenkins流水线stage 步骤中了。

下一步 镜像打包上传,Jenkins流水线 代码如下:

stage('镜像打包上传') {
                    when {
                        expression { deploy == true || deploy == 'true' }
                    }
                    steps {
                        script {
                        def projectName = "${projectName}"
                        echo "项目容器名称:${projectName}"
                        //镜像名称
                        imageName = "${harborUrl}/${harborUserName}/${projectNameAs}/${imageVersion}/${projectEnv}:${imageVersion}_${env.BUILD_TIMESTAMP}.${env.BUILD_NUMBER}"
                        //构建镜像
                        //sh "export DOCKER_BUILDKIT=0 "
                        sh "sudo DOCKER_BUILDKIT=0 docker build --build-arg projectName=${projectName} -t ${imageName} ${WORKSPACE}/target/settings/server "
                        //harbor登录
                        sh "sudo docker login --username=${harborUserName} --password=${harborPwd} ${harborUrl}"
                        //推送镜像
                        sh "sudo docker push ${imageName}"
                        }
                    }
                }

第三步 dockerfile 文件修改

FROM alpine:latest

LABEL MAINTAINER="wwwzhouhui"

WORKDIR /home/ahzz

COPY  ./server ./
COPY  ./resource/ ./resource
COPY  ./config.yaml ./config.yaml
COPY  ./dongtai-go-agent-config.yaml ./dongtai-go-agent-config.yaml

RUN  chmod +x /home/ahzz/config.yaml ;\
     chmod +x /home/ahzz/dongtai-go-agent-config.yaml ;\
     chmod +x /home/ahzz/server ;

EXPOSE 8080
ENTRYPOINT ./server

从以上dockerfile 它实际上就干了一件事就是复制server 二进制文件和resource 以及 配置文件config.yaml、dongtai-go-agent-config.yaml到镜像里面,并赋予docker 权限。

以上步骤就完成 流水线代码+dockerfile 文件的修改。

我们对比一下2个构建时间消耗

大家有没有发现 从1分14秒一下缩短到15秒中。缩短的时间差不多就是 go 第三方依赖包的下载。

我们对比了一下前后 构建时间 效率整整提升了 (16+74)/(12+15+5+1)=2.7倍。一次构建提升了2.7 多个项目多次构建一年下来这个时间是惊人的。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言