拉取、编译、部署,无人机升空!
编译型语言,就需要自动部署
我记得上学期刚注册助手 Gita 时,我还打趣地问过部长,助手什么时候上 CI / CD? 当时部长说快了,这学期就上。
现在助手可以说每个项目完成后,都会使用 Drone 实现持续交付 / 持续集成。
对于前端来说,因为助手主要是用 Vue 做单页应用,推送代码到 Gitea 上后,Drone 会使用 Vue CLI 对项目进行编译,之后将编译好的前端静态文件放进一个用 Go 写的小型服务端中。最后是一个可执行二进制文件的形式。在服务器上将这个二进制文件当作为一个service
执行即可。
而后端部分,则是 Go 直接编译出二进制文件。之后有两种方法:一种是直接和前端一样,将二进制文件当做service
执行;另一种是使用Dockfile
打包成Docker
镜像,推送到阿里云的镜像托管服务后,再以单个 Docker 容器的形式部署。这种方式的好处在于,阿里云的镜像托管是可以存储不同版本的镜像的,方便实现版本的回滚。
来搭个 Drone 吧~
我从这学期开始尝试学着写 Golang,确实挺为之着迷的。因为她没有 Python 那样的性能缓慢,速度之快地直逼 C 语言;同时又没有 C 语言那样的“语法残废”,该有的常用库都有,并且因为是官方的包,因此都是经过很细致的优化的,性能方面是有保障的。 好的,日常吹完 Go 了,开始聊正事了。 Golang 作为一个编译型语言,不像 PHP 那样有问题可以方便直接地修改文件内容即可。Golang 需要编译!!并且最后编译出来的还是一个小巧的二进制可执行文件。还得手动去执行它。因此,我也急需一个像助手一样的持续化自动部署平台——我在 GitHub 上的 Webhook 能触发她,她能自动拉取我的代码,自动编译,打包成 Docker 镜像,然后生成 Docker 容器。Drone 就是这样一个基于 Docker 的 CI / CD 平台。 昨天花了一天时间静下心来,终于配好了。还是照常踩了不少坑,借此文来记录一下。
建立 Drone Docker 容器
我是将 Drone 搭在 Docker 里,暴露出 80 端口,然后使用 Nginx 反代一个域名上去。 建立 Drone 镜像的过程可以参考官方的文档。这里提一下,我是想让 Drone 拉取我 GitHub 上的项目,因此需要与我的 GitHub 关联并使用 GitHub 登录。所以我们需要在自己的 GitHub 账号下创建一个 Oauth 应用。这里可以参照官方的文档。 https://docs.drone.io/installation/github/single-machine/
之后创建 Drone 容器,将其中的参数替换成 GitHub Oauth 应用的信息即可:
docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/lib/drone:/data \
--env=DRONE_GITHUB_SERVER=https://github.com \
--env=DRONE_GITHUB_CLIENT_ID={% your-github-client-id %} \
--env=DRONE_GITHUB_CLIENT_SECRET={% your-github-client-secret %} \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_SERVER_HOST=ci.github.red \
--env=DRONE_SERVER_PROTO=http \
--env=DRONE_TLS_AUTOCERT=false \
--env=DRONE_USER_CREATE=username:wuhan005,admin:true \
--publish=8001:80 \
--publish=8002:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:1
开通阿里云镜像托管服务
我所想要的 Golang 部署是编译项目后,将项目放在一个 Docker 容器内运行。因此我们是需要将项目打包成一个 Docker 镜像,再依靠镜像进行部署。而镜像是要上传到阿里云做镜像托管的。
找到阿里云的容器镜像服务
,在访问凭证
里面设置我们的访问的密码,访问的账号是和阿里云的用户名一样的。
命名空间
,我们的镜像就在这个命名空间下。之后就可以创建单个项目的镜像仓库了。
点击进入后,可以查看当前镜像仓库Registry
的地址。编写.drone.yml
文件
Drone 默认是将项目根目录下的.drone.yml
文件当做配置文件进行相关部署任务的。
直接上我的配置,之后再解释:
workspace:
base: /go
path: src
pipeline:
build:
commands:
- export GOPROXY=https://go-proxy.github.red
- export GO111MODULE=on
- go mod tidy
- CGO_ENABLED=0 go build
publish:
image: plugins/docker
secrets: [docker_username, docker_password, docker_registry]
repo: registry.cn-hongkong.aliyuncs.com/eggplant/drone-test
dockerfile: ./Dockerfile
tags: latest
deploy:
image: docker:latest
volumes: [/var/run/docker.sock:/var/run/docker.sock]
secrets: [docker_username, docker_password, docker_registry]
commands:
- docker login --username=$DOCKER_USERNAME --password=$DOCKER_PASSWORD $DOCKER_REGISTRY
- docker rm -f drone-test || true
- docker pull $DOCKER_REGISTRY/eggplant/drone-test
- docker run -dt --name drone-test -p 8003:12306 $DOCKER_REGISTRY/eggplant/drone-test:latest
volumes: [/var/run/docker.sock:/var/run/docker.sock]
最上面的workspace
指定了当前部署任务的路径。pipeline
里是整套流程的几个步骤。
build
构建
首先是构建(编译)我们的 Golang 程序。Drone 的操作都是基于 Docker 容器进行的,首先它会先创建一个 git 容器用于拉取脚本,然后我们这里指定了image: golang:1.12.4
,即在 Golang 1.12.4 版本的镜像下构建。在该容器下,执行了 4 条命令:
export GOPROXY=https://go-proxy.github.red # 更换 vgo 镜像
export GO111MODULE=on # 开启 vgo 包管理
go mod tidy # 拉取项目所需要的包
CGO_ENABLED=0 go build # 编译项目
publish
推送镜像
下一步是将我们编译好的二进制可执行文件,放入到一个 Docker 镜像中上传至阿里云镜像仓库。使用到了 Drone 的 Docker 插件:plugins/docker
。这里是使用 Dockerfile 生成镜像。
Dockerfile 如下:
FROM alpine:latest
ADD . /home/app/
ENTRYPOINT ["/home/app/drone_test"]
EXPOSE 12306
这里使用了alpine
镜像当做基础镜像进行构建。使用ADD
将我们编译好的二进制可执行文件添加进去。使用ENTRYPOINT
来指定镜像启动时即运行的程序。最后暴露出12306
,即 Golang 服务的端口。
注意这里上传到阿里云的镜像仓库是需要账号密码的,这些敏感信息不能直接暴露在.drone.yml
配置文件中。应该是要在 Drone 面板的项目SETTING
的Secrets
中,设定相关敏感账号密钥信息。在.drone.yml
配置文件中使用secrets: [docker_username, docker_password, docker_registry]
的形式来加入。变量会以大写环境变量的信息注入到容器中。因此这里的 Docker 仓库用户名密码字段请严格使用docker_username
与docker_password
;如需要将 Docker 源地址也不显示,可以使用docker_registry
。
deploy
部署镜像
之后需要将镜像从阿里云镜像仓库拉下来部署为容器。
这里 Drone 会拉取一个 Docker 镜像来实现对宿主机 Docker 的操作。可以看到这里有一个文件卷的映射:volumes: [/var/run/docker.sock:/var/run/docker.sock]
,就是将宿主机中的 Docker daemon 挂载进来。然后就可以直接在宿主机的 Docker 上来创建容器了。
secrets
来处理敏感信息。使用环境变量的形式放进需要执行的命令中。docker login --username=$DOCKER_USERNAME --password=$DOCKER_PASSWORD $DOCKER_REGISTRY
docker rm -f drone-test || true
docker pull $DOCKER_REGISTRY/eggplant/drone-test
docker run -dt --name drone-test -p 8003:12306 $DOCKER_REGISTRY/eggplant/drone-test:latest
首先是登录到阿里云的镜像仓库。然后删除原来的部署容器。
加入项目
在 Drone 中加入项目后,Drone 会自动在 GitHub 的项目中加入一个 WebHook。之后我们的每一次提交都会触发自动部署啦~ 你还可以在.drone.yml
中设置,只部署 master 分支的代码。就可以实现开发 dev 分支,部署 master 主分支啦。
完成啦
至此,整个 Drone 的 Golang 自动部署就完成啦~ 花费了我一天的时间研究。以后就可以舒舒服服地部署 Golang 项目啦。 Drone 其实还可以支持部署 PHP 项目的,但是我个人不是很推荐吧。毕竟有 Deployer 了,强行配上个 Drone 也不需要啦。
喜欢这篇文章?为什么不打赏一下呢?