GitLab CE CI/CD 入门指引手册:从零搭建第一条流水线

作者前言 :这是一篇面向初学者、兼顾进阶实践的 GitLab CE(Community Edition,社区版)CI/CD 学习手册。我会把"是什么 / 怎么搭 / 怎么写 / 怎么避坑"串成一条线,重点讲清楚那些官方文档里分散、教程里常被一笔带过、却恰恰决定你流水线是否好用的关键点。全文图文并茂,配流程图、可执行示例与官方 URL,可直接跟着做。

环境约定:GitLab CE 自建实例(Omnibus 安装),GitLab Runner 注册采用 GitLab 15.10+ 的 authentication token 流程glrt- 前缀)。本文写作时参考 GitLab 17.x 文档,旧版本个别关键字(如 only/except)已标记废弃。

目录

  1. [为什么要学 GitLab CI/CD](#为什么要学 GitLab CI/CD)
  2. [核心概念全景:Pipeline / Stage / Job / Runner](#核心概念全景:Pipeline / Stage / Job / Runner)
  3. [GitLab CE 的安装与 CI/CD 前置配置](#GitLab CE 的安装与 CI/CD 前置配置)
  4. [安装并注册 GitLab Runner](#安装并注册 GitLab Runner)
  5. [.gitlab-ci.yml 完全入门](#.gitlab-ci.yml 完全入门)
  6. [第一个完整流水线(Node.js 示例)](#第一个完整流水线(Node.js 示例))
  7. 进阶关键字与实战技巧
  8. [Cache 与 Artifacts:最容易混淆的一对](#Cache 与 Artifacts:最容易混淆的一对)
  9. [Deploy(部署)与 Environment](#Deploy(部署)与 Environment)
  10. 常见报错与调试秘籍
  11. [CE 与 EE 的功能边界(选型必读)](#CE 与 EE 的功能边界(选型必读))
  12. 学习路线与参考资源

1. 为什么要学 GitLab CI/CD

很多团队用过 Jenkins、GitHub Actions,但对 GitLab 内置的 CI/CD 望而却步。其实 GitLab CI/CD 最大的优势是"一体化":代码仓库、Merge Request、Issue、Runner、流水线全在一个产品里,不需要 Webhook 对接、不需要额外账号、不用装插件。

一句话定义:

GitLab CI/CD 是一套内置的持续集成 / 持续交付引擎。你在仓库根目录放一个 .gitlab-ci.yml,每次 git push 或创建 MR 时,GitLab 自动按它定义的流程跑构建、测试、部署。

它的几个"独到价值":

  • 流水线即代码(Pipeline as Code) :所有流程写在 .gitlab-ci.yml 里,随代码一起版本化、一起走 MR 评审。改流水线本身也要经过 Code Review------这是质量保障常被忽视的一环。
  • 原生集成 MR:测试不通过,MR 就被挡住无法合并,天然形成质量门禁。
  • Runner 可私有化:自建 Runner 跑在自家机器 / K8s 上,敏感代码不出内网(这对金融、政务场景尤其关键)。

💡 独到见解 :很多教程把 CI/CD 讲成"自动跑测试"。真正成熟的理解是------CI/CD 是"把软件交付的每一个人为动作都变成可重复、可回滚的代码" 。从这个角度看,.gitlab-ci.yml 不是配置文件,而是你团队交付流程的"可执行说明书"


2. 核心概念全景:Pipeline / Stage / Job / Runner

先建立整体心智模型,后面每学一个关键字都"知道它属于哪一层"。

图 1:从 git push 到部署的完整链路。GitLab 服务端负责编排,Runner 负责执行,Cache/Artifacts 负责数据流转。

四个核心概念,层层包含:

概念 类比 说明
Pipeline(流水线) 一条完整的"交付流程" 一次触发(push / MR / schedule)产生一条 Pipeline
Stage(阶段) 流程中的大步骤 build → test → deployStage 之间串行
Job(作业) 一个具体任务 unit-testbuild-docker同一 Stage 内的 Job 并行
Runner(执行器) 干活的工人 真正执行 Job 的进程,由 Executor(docker/shell/k8s 等)决定运行环境

🌟 关键认知 :Stage 串行、Job 并行------这是理解执行顺序的"第一性原理"。比如 test 阶段挂了,后面的 deploy 默认就不会跑。

层级关系见图 2:

图 2:Pipeline → Stage → Job 的包含关系。同一 Stage 内多个 Job 并行(受 Runner 并发数约束)。

一次完整流程的时序

复制代码
开发者 git push
   ↓
GitLab 读取 .gitlab-ci.yml,创建 Pipeline
   ↓
按 stages 顺序:build → test → deploy
   ↓ (每个 stage 内的 jobs 并行)
Runner 领取 Job,在指定镜像/环境中执行 script
   ↓
成功 → 进入下一 stage;失败 → 流水线终止(可配置 allow_failure)
   ↓
deploy 完成 → 部署到目标环境

更多必须掌握的术语

  • Executor :Runner 运行 Job 的方式。docker(推荐,隔离好)、shell(直接跑在宿主机)、kubernetes(云原生)等。
  • Artifact / Cache:产物与缓存,详见第 8 章。
  • Variable(变量) :可在 UI 或 YAML 中定义的键值对,敏感信息(Token、密码)务必用 CI/CD Variables(支持 masked & protected)。

3. GitLab CE 的安装与 CI/CD 前置配置

本手册聚焦 CI/CD,安装部分仅给出最小可用路径。生产部署请参考官方文档做资源规划与备份。

3.1 安装 GitLab CE(Omnibus 一键包)

官方推荐 Omnibus 包(所有组件打包在一起)。以 Ubuntu/Debian 为例:

bash 复制代码
# 安装依赖
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates

# 添加 GitLab 包仓库
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

# 安装 CE(EXTERNAL_URL 改成你的域名/IP)
sudo EXTERNAL_URL="https://gitlab.example.com" apt-get install gitlab-ce

安装完成后访问 https://gitlab.example.com,设置 root 密码即可。

3.2 开启 CI/CD 并注册 Runner

新版本 GitLab 中,Runner 采用新式的 "authentication token" 流程(Project / Group / Instance 三级):

  1. 进入项目:Settings → CI/CD → Runners → New project runner
  2. 选择操作系统(Linux/macOS/Windows)
  3. 复制生成的 token(形如 glrt-xxxxxxxx)------这是 15.10+ 推荐方式
  4. 用该 token 注册 Runner(见第 4 章)

⚠️ 版本注意 :旧式的 Registration Token 已在 15.6 废弃,并将在 GitLab 18.0 移除 。网上大量老教程用的 --registration-token 参数在新版会报错 410 Gone新部署请一律使用 authentication token(--token glrt-xxx

官方说明:https://docs.gitlab.com/runner/register/


4. 安装并注册 GitLab Runner

GitLab Runner 是一个独立程序(Go 二进制),建议装在独立于 GitLab 服务端的机器上,避免抢资源。

4.1 安装 Runner

bash 复制代码
# Linux (Ubuntu/Debian)
curl -sS https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-runner

# 验证
gitlab-runner --version

4.2 注册 Runner(非交互模式,推荐)

bash 复制代码
sudo gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.example.com/" \
  --token "glrt-xxxxxxxxxxxxxxxxxxxx" \
  --executor "docker" \
  --docker-image "alpine:latest" \
  --description "docker-runner" \
  --tag-list "docker,linux" \
  --run-untagged="true" \
  --locked="false"

参数说明:

参数 含义
--url GitLab 实例地址
--token 上一步复制的 authentication token(glrt- 前缀)
--executor 执行器类型:docker / shell / kubernetes
--docker-image 兜底镜像(YAML 未指定时用它)
--tag-list Job 通过 tags: 匹配到该 Runner

配置写入 /etc/gitlab-runner/config.toml

4.3 Executor 怎么选?(独到建议)

Executor 隔离性 适用场景
docker ✅推荐 强(每 Job 一个干净容器) 绝大多数构建、测试
shell 无(直接跑宿主机) 需要访问宿主机硬件/特定编译器、GPU
kubernetes 很强 云原生、大规模弹性
docker+machine 强+弹性 需要自动伸缩的大团队

💡 经验之谈

  • 学习与中小团队首选 docker executor------环境干净、可复现,CI 结果不受宿主机污染。
  • 永远不要 把不可信代码用 shell executor 跑在同一台机器上------Job 能以 gitlab-runner 用户权限读取该用户可见的一切。
  • 生产如需自动伸缩,考虑 docker-machine 或 Kubernetes executor。

4.4 启动与验证

bash 复制代码
sudo gitlab-runner start
sudo gitlab-runner list    # 查看已注册 Runner

回到 GitLab 页面 CI/CD → Runners ,应能看到 Runner 处于 Online 绿色状态。


5. .gitlab-ci.yml 完全入门

所有流水线逻辑都写在这个文件里,放在仓库根目录。GitLab 会在每次触发时自动读取它。

5.1 最小可用示例

yaml 复制代码
# .gitlab-ci.yml
stages:
  - test

run-tests:
  stage: test
  image: node:20
  script:
    - npm install
    - npm test

推送后,GitLab 自动创建 Pipeline 并执行。入门要点

  • stages:声明阶段列表,有顺序。
  • stage: test:把 Job 归入某个阶段。
  • image:Job 运行的 Docker 镜像(用 docker executor 时)。
  • script:要执行的 shell 命令列表(这是唯一必填字段)。

5.2 关键字的"分类地图"(记忆框架)

与其死记关键字,不如按"职责"分类理解:

类别 关键字 作用
结构 stages, workflow 定义流水线骨架
Job 基础 script, stage, image, before_script, after_script 定义"做什么"
控制执行 rules, when, needs, dependencies, allow_failure, retry 定义"何时/如何做"
数据传递 cache, artifacts, dependencies 定义"数据怎么流"
环境/部署 environment, deploy 定义"部署到哪"
复用 default, variables, include, extends, !reference 定义"如何复用/参数化"

🌟 独到见解 :把 YAML 当成"声明式编程"来读------你描述期望的最终状态(要跑哪些 job、在什么条件下、产出什么),而不是写一堆 if/else 脚本 。遇到复杂逻辑时,优先用 rulesneedsextends,而不是塞进一个巨大的 script


6. 第一个完整流水线(Node.js 示例)

下面是一个生产级可参考的 Node.js 项目流水线,覆盖 install → test → build → deploy,包含缓存与产物:

yaml 复制代码
# .gitlab-ci.yml
stages:
  - install
  - test
  - build
  - deploy

variables:
  NODE_ENV: test

# ===== 1. 安装依赖(并缓存)=====
install-deps:
  stage: install
  image: node:20
  script:
    - npm ci
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

# ===== 2. 测试阶段(两个 Job 并行)=====
lint:
  stage: test
  image: node:20
  script:
    - npm run lint
  needs: [install-deps]   # 不等待前一 stage,直接按依赖跳转

unit-test:
  stage: test
  image: node:20
  script:
    - npm run test:unit -- --coverage
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
    when: always          # 即使失败也收集报告

# ===== 3. 构建 =====
build-prod:
  stage: build
  image: node:20
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
    - if: '$CI_COMMIT_BRANCH == "develop"'

# ===== 4. 部署(按分支区分环境)=====
deploy-staging:
  stage: deploy
  image: alpine:latest
  script:
    - echo "Deploy to staging..."
    - ./deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

deploy-production:
  stage: deploy
  image: alpine:latest
  script:
    - echo "Deploy to production..."
    - ./deploy.sh prod
  environment:
    name: production
    url: https://www.example.com
  when: manual     # 需手动点击触发(生产防护)
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

这个例子里的"干货"讲解

  1. needs: 打破 stage 串行lint 只需 install-deps 完成即可开始,不必等 install 阶段所有 job 结束------缩短总耗时
  2. rules: 控制部署环境:develop 分支 → 预发,main 分支 → 生产。
  3. when: manual:生产部署必须人工确认,避免误发。
  4. cache + artifacts 双管齐下cache 加速依赖安装,artifactsnode_modules / dist 可靠传递给后续 job。

📖 YAML 关键字完整参考:https://docs.gitlab.com/ci/yaml/


7. 进阶关键字与实战技巧

7.1 rules ------ 控制 Job 何时运行(取代 only/except

rules 是现代 GitLab CI 的核心控制流 。它由一组 if 规则组成,从上到下匹配:

yaml 复制代码
deploy:
  script: echo "deploy"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'    # 定时流水线
      when: manual
      allow_failure: true
    - if: '$CI_COMMIT_BRANCH == "main"'          # main 分支:正常跑
    - if: '$CI_COMMIT_TAG'                       # 打 tag 也跑
    - when: never                                # 其余情况:跳过

常用内置变量:

变量 含义
$CI_COMMIT_BRANCH 当前分支名
$CI_DEFAULT_BRANCH 项目默认分支(推荐用这个代替硬编码 main
$CI_COMMIT_TAG 若为 tag 则非空
$CI_PIPELINE_SOURCE 触发来源:push / merge_request_event / schedule / web
$CI_MERGE_REQUEST_IID MR 编号(用于区分 MR 流水线)

⚠️ 重要only / except 已进入维护模式,官方明确建议迁移到 rulesrules 表达能力更强(支持正则 =~、变量判断、组合条件)。

rules vs only/except 迁移示例(官方等价写法):

yaml 复制代码
# 旧写法(废弃)
job:
  only:
    - main
    - /^release-.*$/
    - schedules

# 新写法(推荐)
job:
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    - if: '$CI_COMMIT_BRANCH =~ /^release-.*$/'
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

7.2 needs + dependencies ------ 有向无环图(DAG)加速

默认流水线按 stage 串行。用 needs 可以声明 Job 间依赖,GitLab 会构建 DAG,不依赖的 Job 立即并行

yaml 复制代码
unit-test:
  stage: test
  needs: [install-deps]   # 只等 install-deps,不等整个 install 阶段

dependencies 则控制"从哪些 Job 下载 artifacts"。

7.3 extends / !reference ------ 复用,别复制粘贴

yaml 复制代码
.default-job:
  image: node:20
  before_script:
    - npm ci

test-a:
  extends: .default-job
  script: [npm run test:a]

test-b:
  extends: .default-job
  script: [npm run test:b]

💡 独到建议 :把"公共部分"抽成 .base(带点号前缀表示隐藏 Job,不会被执行),团队规范由此落地。这是把流水线从"能跑"变成"可维护"的分水岭。

7.4 default ------ 全局默认值

yaml 复制代码
default:
  image: node:20
  retry: 1
  timeout: 10 minutes

7.5 include ------ 拆分大型配置

把公共 CI 模板抽到单独文件甚至独立仓库,用 include 引入------适合多项目共享规范。


8. Cache 与 Artifacts:最容易混淆的一对

这是新手踩坑最密集的地方。看图理解:

图 3:左上为 rules 决策逻辑;下方对比 Cache 与 Artifacts。

8.1 一张表彻底分清

维度 Cache(缓存) Artifacts(产物)
目的 加速(保存依赖) 跨 stage 传递文件
典型内容 node_modules/.npm/.gradle/ 构建包、测试报告、覆盖率
可靠性 尽力而为,可能被回收 可靠,上传到 GitLab
作用域 项目内跨 pipeline 共享(默认) 同一条 pipeline 内跨 job
过期 按 cache policy expire_in(默认 30 天)
口诀 可丢的优化 后续依赖的数据

8.2 Cache 最佳实践

yaml 复制代码
cache:
  key:
    files:
      - package-lock.json   # lock 文件变 → 缓存 key 变 → 重建
  paths:
    - node_modules/
  • key 绑定到 lock 文件:依赖不变就复用缓存,变了就重建,兼顾速度与正确性。
  • policy: pull-push / pull / push 精细控制某 job 只拉不推或只推不拉。

8.3 常见误区

错误 :"用 cache 在 stage 之间传构建产物。"

正确 :stage 间传递文件用 artifacts,cache 只用于依赖缓存。

原因:cache 是"尽力而为"、可能失效,且缓存与 artifacts 指向同一路径时可能互相覆盖(因为 cache 在 artifacts 之前恢复)。


9. Deploy(部署)与 Environment

9.1 environment 关键字

yaml 复制代码
deploy-prod:
  stage: deploy
  script: ./deploy.sh prod
  environment:
    name: production
    url: https://www.example.com

配置后,GitLab 侧边栏出现 Deployments → Environments ,可看到每次部署的版本、支持一键回滚(Rollback)。

9.2 部署保护(Protected Environment)

生产环境可在 Settings → CI/CD → Protected environments 设置:只有特定分支/Tag 才能部署。强烈建议给 production 加保护。

9.3 三种部署触发方式

方式 适用
when: manual 人工审批后点击部署(生产推荐)
rules + 分支 自动部署到对应环境
schedule 定时发布

💡 独到建议 :成熟的交付模型是 "自动部署到 staging,人工确认后部署到 production"------把"可自动化"和"必须人拍板"清晰分开。


10. 常见报错与调试秘籍

10.1 This job is stuck or pending...

原因 :没有可用 Runner,或 Runner 的 tag 与 Job 的 tags: 不匹配。

解决

  • 检查 Runner 是否 Online(CI/CD → Runners)
  • Job 有 tags: [docker] 则 Runner 必须带对应 tag;或用 tags: [] + Runner 勾选 "Run untagged jobs"

10.2 fatal: unable to access 'http://...' 克隆失败

原因 :Runner 无法访问 GitLab(网络/DNS)。

解决:确认 Runner 机器能访问 GitLab URL;自签名 HTTPS 需配置证书。

10.3 docker: command not found

原因 :用 docker executor 却没装 Docker,或 shell executor 的 Job 里调用 docker

解决 :在 Job 中用 image: docker:24-dind + services: [docker:24-dind],并开启 privileged。

10.4 cache: no matching files / 缓存不命中

原因key 变化,或缓存被回收。

解决 :检查 key 规则;多 Runner 时配置 分布式缓存(S3 / MinIO) 保证共享。

10.5 调试技巧

  1. 本地验证 YAML 语法 :项目页 CI/CD → Editor 有内置 Lint。
  2. CI_DEBUG_TRACE=true:在 Variables 里设置,可打印详细执行日志(注意会暴露密钥,用完即删)。
  3. rules: - when: manual 隔离问题 Job,逐段跑。
  4. before_script 打印环境- env | sort 查看可用变量。

11. CE 与 EE 的功能边界(选型必读)

本节帮你在动手前确认:"CE 够不够用?"

GitLab 采用 Open Core(CE 开源免费 + EE 付费增强) 双轨制。CE 永久免费、MIT 协议、可商用。CI/CD 引擎本身在 CE 中已相当完整------内置 Runner、YAML 编排、并行 Job、基础 MR 流水线等核心能力 CE 都具备。

能力维度 GitLab CE(免费) GitLab EE(付费)
CI/CD 引擎 ✅ Runner、YAML、并行 Job ✅ 增强的流水线拓扑图、跨变量继承
安全扫描 ⚠️ 基础 SAST ✅ SAST/DAST、依赖扫描、License 合规
高可用 ❌ 单机(所有服务同机) ✅ PG/Redis/Gitaly 拆分、多节点
审计/治理 ❌ 仅全局操作日志 ✅ 细粒度审计、IP 白名单、SSO
合规场景 需自研补足 ✅ SOC2 / HIPAA 等

🌟 选型建议

  • 个人学习 / 小团队 / 源码不出内网 → CE 完全够用,CI/CD 能力不打折扣。
  • 强合规(金融/政务)、需要 DAST/依赖扫描、高可用 → 评估 EE。
  • ⚠️ 注意:自 2021 年起 GitLab 逐步把部分协作/治理能力从 CE 迁移到 EE(Open Core Progressive Licensing),且 gitlab.com SaaS 免费层有 CI 分钟数 / 并发数限制。自建 CE 不受分钟数限制(受你自己的硬件限制)。

12. 学习路线与参考资源

12.1 推荐学习路线

  1. 跑通最小流水线(第 5 章)→ 建立信心
  2. 加缓存 + artifacts(第 8 章)→ 提速、解决数据传递
  3. rules 控制环境(第 7、9 章)→ 实现真正的 CD
  4. **抽公共模板(extends / include)**→ 可维护
  5. 加保护环境 + 人工审批 → 生产可用

12.2 官方参考资源(建议收藏)

资源 链接
GitLab 官方文档首页 https://docs.gitlab.com/
CI/CD 入门(Quick Start) https://docs.gitlab.com/ci/quick_start/
.gitlab-ci.yml 关键字参考 https://docs.gitlab.com/ci/yaml/
Runner 注册文档 https://docs.gitlab.com/runner/register/
rules 官方文档 https://docs.gitlab.com/ci/jobs/job_rules/
缓存机制文档 https://docs.gitlab.com/ci/caching/
GitLab 安装 https://about.gitlab.com/install/

12.3 结语

CI/CD 不是"学会一个工具",而是"建立一套工程纪律"。

GitLab CI/CD 把这套纪律浓缩成一个 .gitlab-ci.yml------它既是自动化脚本,也是团队交付规范的载体。建议你从今天的最小例子开始,每加一个关键字,都想想它解决了什么实际问题 。当你能熟练用 rules 控制环境、needs 编排 DAG、cache/artifacts 管理数据、environment 做受保护部署时,你就已经超越了"入门",进入了"能设计交付系统"的阶段。

祝你在 GitLab CI/CD 的路上越走越顺 🚀


相关推荐
chens1231233 小时前
自建三节点 K3s 集群搭建 Drone CI/CD 流水线
ci/cd
2501_9289962217 小时前
Agent 开发的 API 选型:从 Function Calling 到多模型协作的中科热备底层逻辑
服务器·重构·gitlab
何以解忧,唯有..1 天前
Claude Code 常用操作总结
gitlab
GGG7661 天前
K8s1.28 全栈落地|Jenkins+GitLab+Harbor DevOps 流水线封神实战
kubernetes·gitlab·jenkins
Patrick_Wilson2 天前
为什么gitlab的MR会默认有一个merge commit
前端·git·gitlab
虎王物联2 天前
Docker BuildKit多阶段构建:IoT固件交叉编译流水线实战
运维·物联网·ci/cd·docker·容器·物联网嵌入式
LlmCraft|大模型工程实践2 天前
14. CI/CD 流水线中集成 Docker:GitHub Actions 自动构建部署
ci/cd·docker·github
极小狐2 天前
极狐GitLab Duo 功能更新:扩展 MCP 工具集、支持 MR 事件触发
运维·gitlab·agent·mr·极狐gitlab·mcp·极狐gitlab duo
2501_928996223 天前
GitLab CVE-2026-19478漏洞解析:Gitaly ref攻击绕过审计与中科热备下的代码资产保护重构
重构·gitlab