内容简介:本文为转载,原文:
本文为转载,原文: Golang基于Gitlab CI/CD部署方案
docker
概述
持续集成 (Continuous integration)是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
持续部署 (continuous deployment)是通过自动化的构建、测试和部署循环来快速交付高质量的产品。某种程度上代表了一个开发团队工程化的程度,毕竟快速运转的互联网公司人力成本会高于机器,投资机器优化开发流程化相对也提高了人的效率,让 engineering productivity 最大化。
1. 环境准备
本次试验是基于 Centos 7.3 , docker 17.03.2-ce 环境下的。docker的安装这里就不赘述了,提供了官方链接吧: Get Docker CE for CentOS
1.1. docker启动gitlab
启动命令如下:
docker run --detach \ --hostname gitlab.chain.cn \ --publish 8443:443 --publish 8080:80 --publish 2222:22 \ --name gitlab \ --restart always \ --volume /Users/zhangzc/gitlab/config:/etc/gitlab \ --volume /Users/zhangzc/gitlab/logs:/var/log/gitlab \ --volume /Users/zhangzc/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce
port,hostname, volume根据具体情况具体设置
1.2. docker启动gitlab-runner
启动命令如下:
sudo docker run -d / --name gitlab-runner / --restart always / -v /Users/zhangzc/gitlab-runner/config:/etc/gitlab-runner / -v /Users/zhangzc/gitlab-runner/run/docker.sock:/var/run/docker.sock / gitlab/gitlab-runner:latest
volume根据具体情况具体设置
1.3. 用于集成部署的镜像制作
我们的集成和部署都需要放在一个容器里面进行,所以,需要制作一个镜像并安装一些必要的工具,用于集成和部署相关操作。目前我们的项目都是基于golang 1.9.2的,这里也就基于golang:1.9.2的镜像制定一个特定的镜像。
Dockerfile内容如下:
# Base image: https://hub.docker.com/_/golang/
FROM golang:1.9.2
USER root
# Install golint
ENV GOPATH /go
ENV PATH ${GOPATH}/bin:$PATH
RUN mkdir -p /go/src/golang.org/x
RUN mkdir -p /go/src/github.com/golang
COPY source/golang.org /go/src/golang.org/x/
COPY source/github.com /go/src/github.com/golang/
RUN go install github.com/golang/lint/golint
# install docker
RUN curl -O https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz \
&& tar zxvf docker-latest.tgz \
&& cp docker/docker /usr/local/bin/ \
&& rm -rf docker docker-latest.tgz
# install expect
RUN apt-get update
RUN apt-get -y install tcl tk expect
其中 golint 是用于golang代码风格检查的工具。
docker 是由于需要在容器里面使用宿主的 docker 命令,这里就需要安装一个docker的可执行文件,然后在启动容器的时候,将宿主的 /var/run/docker.sock 文件挂载到容器内的同样位置。
expect 是用于ssh自动登录远程服务器的工具,这里安装改 工具 是为了可以实现远程服务器端部署应用
另外,在安装golint的时候,是需要去golang.org下载源码的,由于墙的关系,go get命令是执行不了的。为了处理这个问题,首先通过其他渠道先下载好相关源码,放到指定的路径下,然后copy到镜像里,并执行安装即可。
下面有段脚本是用于生成镜像的:
#!/bin/bash echo "提取构建镜像时需要的文件" source_path="source" mkdir -p $source_path/golang.org mkdir -p $source_path/github.com cp -rf $GOPATH/src/golang.org/x/lint $source_path/golang.org/ cp -rf $GOPATH/src/golang.org/x/tools $source_path/golang.org/ cp -rf $GOPATH/src/github.com/golang/lint $source_path/github.com echo "构建镜像" docker build -t go-tools:1.9.2 . echo "删除构建镜像时需要的文件" rm -rf $source_path
生成镜像后,推送到镜像仓库,并在gitlab-runner的服务器上拉取该镜像
本次试验的gitlab和gitlab-runner是运行在同一服务器的docker下的。
2. runner注册及配置
2.1. 注册
环境准备好后,在服务器上执行以下命令,注册runner:
docker exec -it gitlab-runner gitlab-ci-multi-runner register
按照提示输入相关信息
Please enter the gitlab-ci coordinator URL: # gitlab的url, 如:https://gitlab.chain.cn/ Please enter the gitlab-ci token for this runner: # gitlab->你的项目->settings -> CI/CD ->Runners settings Please enter the gitlab-ci description for this runner: # 示例:demo-test Please enter the gitlab-ci tags for this runner (comma separated): # 示例:demo Whether to run untagged builds [true/false]: # true Please enter the executor: docker, parallels, shell, kubernetes, docker-ssh, ssh, virtualbox, docker+machine, docker-ssh+machine: # docker Please enter the default Docker image (e.g. ruby:2.1): # go-tools:1.9.2 (之前自己制作的镜像)
token
成功后,可以看到gitlab->你的项目->settings -> CI/CD ->Runners settings 页面下面有以下内容:
runner注册成功
2.2. 配置
注册成功之后,还需要在原有的配置上做一些特定的配置,如下:
[[runners]]
name = "demo-test"
url = "https://gitlab.chain.cn/"
token = "c771fc5feb1734a9d4df4c8108cd4e"
executor = "docker"
[runners.docker]
tls_verify = false
image = "go-tools:1.9.2"
privileged = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock"]
extra_hosts = ["gitlab.chain.cn:127.0.0.1"]
network_mode = "host"
pull_policy = "if-not-present"
shm_size = 0
[runners.cache]
这里先解释下gitlab-runner的流程吧,gitlab-runner在执行的时候,会根据上面的配置启动一个容器,即配置中的go-tools:1.9.2,b其中所有的启动参数都会在[runners.docker]节点下配置好,包括挂载啊,网络啊之类的。容器启动成功之后,会使用这个容器去gitlab上pull代码,然后根据自己定义的规则进行检验,全部检测成功之后便是部署了。
volumes : 是为了在容器中可以执行宿主机的docker命令。
extra_hosts : 给gitlab添加个host映射,映射到127.0.0.1
network_mode : 令容器的网络与宿主机一致,只有这样才能通过127.0.0.1访问到gitlab。
pull_policy : 当指定的镜像不存在的话,则通过docker pull拉取
3. 定义规则
在gitlab项目根目录创建 .gitlab-ci.yml 文件,填写runner规则,具体语法课参考官方文档: https://docs.gitlab.com/ee/ci/yaml/
3.1. go集成命令
下面介绍几个golang常见的集成命令
-
包列表
正如在官方文档中所描述的那样,go项目是包的集合。下面介绍的大多数工具都将使用这些包,因此我们需要的第一个命令是列出包的方法。我们可以用go list子命令来完成
go list ./...
请注意,如果我们要避免将我们的工具应用于外部资源,并将其限制在我们的代码中。 那么我们需要去除vendor 目录,命令如下:
go list ./... | grep -v /vendor/
-
单元测试
这些是您可以在代码中运行的最常见的测试。每个.go文件需要一个能支持单元测试的
_test.go文件。可以使用以下命令运行所有包的测试:
go test -short $(go list ./... | grep -v /vendor/)
-
数据竞争
这通常是一个难以逃避解决的问题,go工具默认具有(但只能在linux / amd64、freebsd / amd64、darwin / amd64和windows / amd64上使用)
go test -race -short $(go list . /…| grep - v /vendor/)
-
代码覆盖
这是评估代码的质量的必备工具,并能显示哪部分代码进行了单元测试,哪部分没有。
要计算代码覆盖率,需要运行以下脚本:
PKG_LIST=$(go list ./... | grep -v /vendor/)
for package in ${PKG_LIST}; do
go test -covermode=count -coverprofile "cover/${package##*/}.cov" "$package" ;
done
tail -q -n +2 cover/*.cov >> cover/coverage.cov
go tool cover -func=cover/coverage.cov
如果我们想要获得HTML格式的覆盖率报告,我们需要添加以下命令:
go tool cover -html=cover/coverage.cov -o coverage.html
-
构建
最后一旦代码经过了完全测试,我们要对代码进行编译,从而构建可以执行的二进制文件。
go build .
-
linter
这是我们在代码中使用的第一个工具:linter。它的作用是检查代码风格/错误。这听起来像是一个可选的工具,或者至少是一个“不错”的工具,但它确实有助于在项目上保持一致的代码风格。
linter并不是 go 本身的一部分,所以如果要使用,你需要手动安装它(之前的go-tools镜像我们已经安装过了)。
使用方法相当简单:只需在代码包上运行它(也可以指向. go文件):
$ golint -set_exit_status $(go list ./... | grep -v /vendor/)
注意-set_exit_status选项。 默认情况下,golint仅输出样式问题,并带有返回值(带有0返回码),所以CI不认为是出错。 如果指定了-set_exit_status,则在遇到任何样式问题时,golint的返回码将不为0。
3.2. Makefile
如果我们不想在 .gitlab-ci.yml 文件中写的太复杂,那么我们可以把持续集成环境中使用的所有工具,全部打包在Makefile中,并用统一的方式调用它们。
这样的话, .gitlab-ci.yml 文件就会更加简洁了。当然了,Makefile同样也可以调用 *.sh 脚本文件
3.3. 配置示例
3.3.1. .gitlab-ci.yml
image: go-tools:1.9.2
stages:
- build
- test
- deploy
before_script:
- mkdir -p /go/src/gitlab.chain.cn/ZhangZhongcheng /go/src/_/builds
- cp -r $CI_PROJECT_DIR /go/src/gitlab.chain.cn/ZhangZhongcheng/demo
- ln -s /go/src/gitlab.chain.cn/ZhangZhongcheng /go/src/_/builds/ZhangZhongcheng
- cd /go/src/_/builds/ZhangZhongcheng/demo
unit_tests:
stage: test
script:
- make test
tags:
- demo
race_detector:
stage: test
script:
- make race
tags:
- demo
code_coverage:
stage: test
script:
- make coverage
tags:
- demo
code_coverage_report:
stage: test
script:
- make coverhtml
only:
- master
tags:
- demo
lint_code:
stage: test
script:
- make lint
build:
stage: build
script:
- pwd
- go build .
tags:
- demo
build_image:
stage: deploy
script:
- make build_image
tags:
- demo
3.3.2. Makefile
PROJECT_NAME := "demo"
PKG := "gitlab.chain.cn/ZhangZhongcheng/$(PROJECT_NAME)"
PKG_LIST := $(shell go list ./... | grep -v /vendor/)
GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/ | grep -v _test.go)
test: ## Run unittests
@go test -v ${PKG_LIST}
lint: ## Lint the files
@golint ${PKG_LIST}
race: ## Run data race detector
@go test -race -short ${PKG_LIST}
coverage: ## Generate global code coverage report
./scripts/coverage.sh;
coverhtml: ## Generate global code coverage report in HTML
./scripts/coverage.sh html;
build_image:
./scripts/buildDockerImage.sh
3.3.3. coverage.sh
#!/bin/bash
#
# Code coverage generation
COVERAGE_DIR="${COVERAGE_DIR:-coverage}"
PKG_LIST=$(go list ./... | grep -v /vendor/)
# Create the coverage files directory
mkdir -p "$COVERAGE_DIR";
# Create a coverage file for each package
for package in ${PKG_LIST}; do
go test -covermode=count -coverprofile "${COVERAGE_DIR}/${package##*/}.cov" "$package" ;
done ;
# Merge the coverage profile files
echo 'mode: count' > "${COVERAGE_DIR}"/coverage.cov ;
tail -q -n +2 "${COVERAGE_DIR}"/*.cov >> "${COVERAGE_DIR}"/coverage.cov ;
# Display the global code coverage
go tool cover -func="${COVERAGE_DIR}"/coverage.cov ;
# If needed, generate HTML report
if [ "$1" == "html" ]; then
go tool cover -html="${COVERAGE_DIR}"/coverage.cov -o coverage.html ;
fi
# Remove the coverage files directory
rm -rf "$COVERAGE_DIR";
3.3.4. buildDockerImage.sh
#!/bin/bash #检测GOPATH echo "检测GOPATH" if [ -z "$GOPATH" ];then echo "GOPATH 未设定" exit 1 else echo "GOPATH=$GOPATH" fi #初始化数据 echo "初始化数据" new_version="1.0.0" old_version="1.0.0" golang_version="1.9.2" app_name="application" projust_root="demo" DOCKER_IMAGE_NAME="demo" REGISTRY_HOST="xxx.xxx.xxx.xxx:5000" path="/go/src/_/builds/ZhangZhongcheng/demo" #当前容器更换为旧标签 echo "当前容器更换为旧标签" docker rmi $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$old_version # 基于golang:1.9.2镜像启动的容器实例,编译本项目的二进制可执行程序 echo "基于golang:1.9.2镜像启动的容器实例,编译本项目的二进制可执行程序" cd $path go build -o $app_name echo "检测 $app_name 应用" FILE="$path/$app_name" if [ -f "$FILE" ];then echo "$FILE 已就绪" else echo "$FILE 应用不存在" exit 1 fi #docker构建镜像 禁止在构建上下文之外的路径 添加复制文件 #所以在此可以用命令把需要的文件cp到 dockerfile 同目录内 ,构建完成后再用命令删除 cd $path/scripts echo "提取构建时需要的文件" cp ../$app_name $app_name # 基于当前目录下的Dockerfile构建镜像 echo "基于当前目录下的Dockerfile构建镜像" echo "docker build -t $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version ." docker build -t $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version . # 删除本次生成的可执行文件 以及构建所需要的文件 echo "删除本次生成的可执行文件 以及构建所需要的文件" rm -rf $app_name rm -rf ../$app_name #查看镜像 echo "查看镜像" docker images | grep $DOCKER_IMAGE_NAME #推送镜像 echo "推送镜像" echo "docker push $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version" docker push $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version echo "auto deploy" ./automationDeployment.sh $new_version $old_version
3.3.5. automationDeployment.sh
#!/usr/bin/expect
#指定shebang
#设定超时时间为3秒
set ip xxx.xxx.xxx.xxx
set password "xxxxxxx"
set new_version [lindex $argv 0]
set old_version [lindex $argv 1]
spawn ssh root@$ip
expect {
"*yes/no" { send "yes\r"; exp_continue}
"*password:" { send "$password\r" }
}
expect "#*"
send "cd /root/demo/\r"
send "./docker_run_demo.sh $new_version $old_version\r"
expect eof
3.3.6. Dockerfile
FROM golang:1.9.2 #定义环境变量 alpine专用 #ENV TIME_ZONE Asia/Shanghai ADD application /go/src/demo/ WORKDIR /go/src/demo ADD run_application.sh /root/ RUN chmod 755 /root/run_application.sh CMD sh /root/run_application.sh EXPOSE 8080
3.3.7. run_application.sh
#!/bin/bash #映射ip cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime cd /go/src/demo/ ./application
4. 结果
以下为部署成功后的截图:
result
完
转载请注明出处: Golang基于Gitlab CI/CD部署方案
以上所述就是小编给大家介绍的《Golang基于Gitlab CI/CD部署方案》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 基于Kubernetes的持续部署方案
- 前端自动化部署方案探索
- Golang基于GitLab CI/CD部署方案
- golang jenkins部署及slb平滑上线方案
- 企业MySQL5.7.20多实例部署方案
- K8S1.14高可用生产集群部署方案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Build Your Own Web Site the Right Way Using HTML & CSS
Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95
Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!