自动化并不陌生
上一回,我通过 10 分钟的宕机和一份事故说明,得到了一次刻骨铭心的教训。部署不是魔法,而必须是一连串严格的安全装置,也就是“Git,记录 – Test,验证 – Build,打包 – Deploy,配送”。
现在目标已经很明确了。这样复杂又烦人的安全装置,不可能每次都靠我亲手去一个个确认。我需要一个“勤快的机器人”,即使我下班了,或者去休假了,它也能替我继续干活。
“自动化?这是不是也太夸张了点?”
一开始我也先被吓到了,但仔细想想,其实我早就接触过很相似的东西。就是上一套系列里提到的“Docker”。
只要我们在 Dockerfile 里写上“安装 Ubuntu,安装 Java,复制代码”,Docker 就会读取它,并自动把服务器环境搭起来。正因为如此,我们才从一条条手敲命令的苦力活中解放出来。
“CI/CD 流水线”也是完全一样的道理。如果说 Docker 自动化的是“服务器搭建”,那么流水线自动化的就是“整个部署流程”。只不过,它的舞台从我电脑里的小世界,扩展成了“GitLab 和生产服务器”这个更大的场景。

CI/CD:自动化的传送带
现在,就让我们在自己的“数字物流中心”里铺上一条“自动化生产线”吧。听起来很宏大,但原理其实很简单。
1. CI (Continuous Integration,持续集成)
- 含义:“持续地把开发者们的代码合并到一起,并进行检查。”
- 作用:[构建 + 测试]。我刚把代码推上去,机器就会帮我确认“语法对不对?”“原有功能有没有被弄坏?”。次品就在这一步被筛掉。
2. CD (Continuous Delivery/Deployment,持续交付/部署)
- 含义:“把检查完毕的代码交付到客户手里。”
- 作用:[生成镜像 + 部署到服务器]。把通过检查的合格产品 (Docker Image) 装上卡车送到生产服务器,并一直负责到让它运行起来为止。
流水线的设计图:.gitlab-ci.yml
“所以,要怎么让那个机器人干活呢?” 在 GitLab 里,你只需要在项目最上层路径创建一个名为 .gitlab-ci.yml 的文件。这就是要交给机器人的“工作指令书”。
还记得上一次我亲身经历的手动部署之痛吗?我们把那个过程原封不动地翻译成代码就行了。就像写 Dockerfile 一样,一行一行地写下来。
# .gitlab-ci.yml(作業指示書)
stages: # 1. 定義整體作業順序
- test # (第 1 階段:檢查)
- build # (第 2 階段:打包)
- deploy # (第 3 階段:出貨)
# [第1階段] 測試:機器啊,幫我看看程式碼有沒有問題(CI)
unit_test_job:
stage: test
image: openjdk:17-alpine # 在已安裝 Java 的環境中執行
script:
- ./gradlew test # "執行測試程式!" (避免上次的失誤)
# [第2階段] 建置:測試通過後就打包成映像檔(CI)
build_image_job:
stage: build
image: docker:latest # 在已安裝 Docker 的環境中執行
script:
- docker build -t my-app:v1 . # "建構映像檔!"
- docker push my-regisry/my-app:v1 # "推到登錄機!" (回滾標籤必備)
# [第3階段] 部署:把它放到正式伺服器上(CD)
deploy_job:
stage: deploy
script:
- ssh user@server "docker service update my-app" # "更新伺服器!"
有了这一个文件就够了。在我执行 git push 的瞬间,也就是 Trigger 的瞬间,GitLab 就会读取这份指令书,然后唤醒一个名叫“GitLab Runner”的工人机器人去执行任务。
[Check] 我们必须准备好的安全装置
在这条流水线里,上一次让我刻骨铭心的“3 个安全装置”全都被融进去了。
- Git (Trigger):
- 我在本地
push代码这个动作本身,就是流水线的“启动按钮”。没有留下记录 (Commit),部署也就不会开始。
- 我在本地
- Unit Test (Quality Gate):
- 如果
unit_test_job里的测试失败了呢?流水线会立刻“停下来 (Fail)”,从源头上杜绝次品流入下一个阶段(构建/部署)。(以后再也不能因为忙就跳过测试了!)
- 如果
- Docker Image (Artifact):
- 构建阶段生成的镜像会被安全地保存在 Docker Hub 上。就算之后服务器挂了,只要有这个镜像,1 秒钟就能恢复。

实务建议:流水线是活的
不要一开始就试图写出一条完美的流水线。我最初也只是做了 build 和 deploy 两个阶段,直到出了事故之后,才把 test 阶段补到前面去。
- 初期:构建 -> 部署(先以实现自动化为目标)
- 中期:测试 -> 构建 -> 部署(加上安全装置)
- 成熟期:测试 -> 静态分析 (SonarQube) -> 构建 -> 部署到开发服务器 -> (审批) -> 部署到生产服务器
流水线是一个会随着团队成长速度不断进化的“活系统”。
结语:指令书写好了,可是谁来干活?
现在,完美的设计图 .gitlab-ci.yml 已经完成了。但写在纸上的指令书并不会自己动起来。就像有了 Dockerfile 也必须先装好 Docker Daemon 才能运行一样,流水线指令书也需要一个真正流汗干活、负责编译并执行代码的“现场机器人”。
这个机器人的名字叫“GitLab Runner”。工厂主管,也就是 GitLab Server,只负责下达指令,真正干活的是这个 Runner。
下一次,我们就在自己的电脑或一台独立服务器上安装这个 Runner,并把它和 GitLab 连接起来,真正让流水线跑起来。自动化的第一颗扣子,终于要扣上了。


