前言
在写完基于 Webhooks 的"第一篇《都9012年了,你还在手动部署代码吗》"之后,有同学评论到"至少你得用个 docker 啊""一对一嘛...感觉面试吹这个会被吊起来锤"....于是我决定出一篇基于 Docker 的自动部署文章 (:
这是一篇利用 Docker 和 Gitlab-CI 的学习自动部署和实践的笔记,如果您是 Docker 资深玩家,跪求大佬不要吊锤;如果您是萌新,刚开始 Docker 学习之旅,那么希望笔记中的理解和操作能够对您有所帮助.
然鹅,饱和的需求和人的惰性让第二篇拖到了今天ORZ!!! 王者峡谷一时爽,一直王者一直爽
背景
偷懒是第一生产力,当你享受过自动化带给你的便捷时,再也不会想回到手动打包部署上传的"石器时代".
目标
在本地开发完成 push 后,集成环境能够自动完成测试部署打包上传 FTP
前置条件
- 位于内网服务器的 Gitlab 源码仓库(版本支持 Gitlab-CI )
- 位于内网服务器的集成测试环境(能够 Pull 远程仓库代码)
- 集成测试服务器能够安装 Docker
行动
工欲善其事必先利其器,开始行动前有必要理解一波 Docker 和 Gitlab-CI 自动部署原理;
这波要理解的东西有点多,不过不慌,我们一个一个来 !
Docker
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口. 它将应用程序与该程序的依赖,打包在一个文件里面. 运行这个文件,就会生成一个虚拟容器. 程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样. 有了 Docker,就不用担心环境问题.
Docker 容器常常拿来和虚拟机 VM 相比较,提到 VM ,就不得不说....别提了,我还记得当年在大学的虚拟机课程,等虚拟机启动的时间里,老师可以寂寞地抽完几根烟...
有几个概念我们需要理解一下:
- Image (镜像)
- Container (容器): 运行镜像
- Repository (仓库): 储存镜像
我们首先根据文档在集成服务器上安装 Docker => CentOS7上安装Docker
不建议各位同学在window系统上尝试 Docker ,过程及其残忍
我在这次部署中常用的docker命令:
docker search NAME 搜索image镜像
docker pull NAME 拉取image镜像
docker run -d -p 2222:22 --name NAME <IMAGE> 后台运行IMAGE命名为NAME并映射容器端口22到宿主机端口2222(-d:后台运行 -p:端口映射)
docker ps 查看正在运行的docker容器
docker images 查看本地所有镜像
docker stop NAME 停止容器
docker rm 删除容器
docker exec -it <IMAGE> bash 以伪终端交互方式进入容器,运行bash
理解Gitlab-CI自动部署原理
本地仓库 -> (push提交代码) -> 远程仓库(Gitlab-CI) -> (通知注册完成的runner) -> 集成服务器(runner Executor执行命令)-> 打包上传FTP
通过简单的比较我们可以发现,整个流程和使用 webhooks 并无太大差别,但是区别于webhooks 使用 Token 请求具体服务, Gitlab-CI 会找出与这个工程相关联的Runner,并通知这些Runner, 然后这些Runner在宿主机上更新代码, 进行测试, 自动部署, 打包上传.
我们可以把 Gitlab-CI 和 Runner 看做工厂和工人的关系, 工人在工厂里先注册, 工厂开工的时候通知工人干活 ~
配置远程仓库Gitlab-CI
理解完原理后我们来配置(搞定)Gitlab-CI(Gitlab-8.0版本以后默认集成Gitlab-CI):
找到项目 Project 的 Settings 中的 CI/CD, 点击 Runners settings.这时你会发现两种 Runners:
- Shared Runners: 管理员才有资格创建的所有工程都能使用的 Runner
- Specific Runners: 拥有访问权限的人为指定工程创建的 Runner
这里我们使用 Specific Runner, 记住 Specific Runner 配置里的 URL 和 token, 等下我们就是利用这两个参数在集成服务器配置 Runner 和 Gitlab-CI 建立联系 !
集成服务器(宿主机)配置
这里 Gitlab-runner 的安装方式分两种:
- 使用 yum install gitlab-ci-multi-runner安装
- 使用 Docker 安装 Gitlab-runner
我们这里使用 Docker 安装 Gitlab-runner , 注意: 操作前修改 Docker 镜像源为国内源
ps: 注意一下 Gitlab 和 Gitlab-runner 的版本是否匹配, 否则 runner 可能连不上 Gitlab-CI
下载Gitlab-runner
docker search gitlab-runner
docker pull gitlab/gitlab-runner
运行Gitlab-runner,将容器gitlab-runner config.toml映射到主机,方便修改
docker run -d --name gitlab-runner --restart always
-v /data/docker/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner
进入Gitlab-runner bash
docker exec -it gitlab-runner bash
Gitlab-runner注册runner
gitlab-runner register
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
gitlab-ci URL
Please enter the gitlab-ci token for this runner:
gitlab-ci Token
Please enter the gitlab-ci description for this runner:
输入runner名字/描述即可
Please enter the gitlab-ci tags for this runner (comma separated):
输入runner的tag *后面编辑.gitlab-ci.yml需要用到这个tag
Whether to run untagged builds [true/false]:
[false]: 是否运行没有tag的构建
Whether to loack the Runner to current project [true/false]:
[true]: 是否锁定此Runner到正确的project
Registering runner... succeeded runner=******
Please enter the executor: docker, docker-ssh, shell, ssh, docker-ssh+machine, kubernetes, parallels, virtualbox, docker+machine:
选择执行器类型 这里我们选docker
Please enter the default Docker iamge (e.g. ruby: 2.1):
选择执行Docker运行的image镜像 这里我打包了一个服务node环境镜像到本地使用 如果项目服务需要什么依赖,比如数据库之类的也可以打包到镜像中
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded !
此时Runner创建成功!
docker restart gitlab-runner
重启一下gitlab-runner
此时我们刷新 Gitlab-CI -> Settings -> CI/CD -> Runners settings 页面可以看到我们刚刚注册的 Runner 已经出现了 !
ps: 具体 Runner 配置参数可以在 gitlab-runner 容器里 /etc/gitlab-runner 的 config.toml 文件查看和修改
项目 .gitlab-ci.yml 配置
Gitlab-CI 会在仓库发生 push 时通知 Runner 执行脚本动作,具体的脚本动作就需要我们在项目目中新建 .gitlab-ci.yml 编写:
小贴士:
stages 可以拥有多个不重名的 job
我们可以根据自己项目的实际情况编写属于自己的 job
script 定义由Runner执行的shell脚本或命令
before_script 覆盖在作业之前执行的脚本或命令
tags 定义job所适用的runner,tags为runner标签
cache 定义需要被缓存的文件、文件夹列表
具体更多配置推荐阅读官方文档
# 这是我的 .gitlab-ci.yml
stages:
- test
- deploy
- package
# 测试job
test:
stage: test
script:
- npm config set registry https://registry.npm.taobao.org
- npm i
- npm run test
cache:
# key: "$CI_BUILD_REF_NAME"
paths:
- node_modules
tags:
- ego
# 部署job
deploy-dev:
stage: deploy
before_script:
- echo "Start to deploy to dev host"
script:
- echo "deploy front ...."
- sh deploy-front.sh
- echo "deploy backend ...."
- sh ./app/deploy-backend.sh
only:
- /^release\/.*/
tags:
- dennis
- node
# 打包job
package:
stage: package
before_script:
- echo "Start to deploy to dev host"
only:
- /^release\/.*/
script:
- echo "start package..."
- sh package.sh $VERSION
when: manual
tags:
- dennis
- node
Gitlab CI/CD 的 Pipelines 中每一次提交的 stages 就是根据 .gitlab-ci.yml 中的配置形成的, 你可以在Pipelines 中看到你每一次提交的 job 执行情况(成功/失败/等待/取消等状态), 因为网络情况的失败除了可以自动重试外, 我们还可以手动点击重试.
这里的 deploy-front.sh deploy-backend.sh package.sh 前后端部署打包命令就不详细展示了,大家可以根据自己的项目实际情况编写.
ps: 这里要注意一下脚本命令在环境中的执行权限
最后,今天的文章到这里就差不多要结束了,其实当中每个部分都可以深入学习很久,我在文章中也是最粗浅的运用,总目标都是为搭建一整套流程,运行畅通服务,如果您对其中某个部分比如 Dokcer , .gitliab-ci.yml 感兴趣,可以自主深入学习,我也在文章中给出了官网文档~
有关多机部署
虽然Runner可以分布在不同的主机上,同一个主机上也可以有多个Runner。难道我们要在每个部署服务器上都安装运行 Gitlab-runner 吗 ? 这里引用我第一篇文章中 @Axetroy老哥的评论:
恕我直言,服务端需要安装配套工具(服务)的,都是垃圾。
有 10 机器,就得给这 10 台机器安装工具(服务),例如这里是用 nodejs 写的 hook 接受服务 (当然可以解决,自己基于 centerOS 打包一个 Docker 镜像,内置 nodejs 和 hook 服务,然后这 10 台机器就以这个镜像开启。当然这并不是所有的服务器商都支持自定义镜像)
能纯客户端部署的,才是好的。在 CI 构建成功的阶段,只要 CI 的环境变量服务器 IP,端口,用户名和密码,就能通过 SSH 部署。
结果
好了, 又构建失败发邮件了,待我去看看什么问题 (:
最后的最后感谢强哥,在我学习使用 Docker 和 Gitlab-CI 的过程中给予的巨大帮助 ! ! !