Skip to main content

CI/CD 使用指南

先选方式

需求 方式 runner tag
编译 / 打包 / 测试 / 部署等日常作业 常规 job 不用写(公共 runner)
只构建并推送镜像 kaniko 不用写(公共 runner)
docker run / compose 等 Docker in Docker DinD dind(公共 runner)

tags 怎么填:

  • 用公共(共享)runner:不写 tags(常规 job、kaniko 就是这种;也可显式写 tags: [docker])。
  • 用公共 dind:必须写 tags: [dind](dind)——只有带这个 tag 的 runner 提供 job 内 Docker。
  • 用你自己的 runner(自建本地 runner):写你注册时设的 tag,例如 tags: [myrunner]。 注意:项目里有自己的 runner 且开了 "Run untagged jobs" 时,不写 tags 的 job 会优先被它接走(通常正是你想要的)。

常规 job

  • 编译、打包、测试、代码检查、部署……这些都是同一类「常规 job」:在 job 容器里跑命令、不构建镜像。

下面示例以 Node 前端为例;

compile:
  stage: build
  image: node:lts                 # 换成你需要的通用镜像
  script:
    - npm ci
    - npm run build
    - npm test
  artifacts:
    paths: [dist/]
  • 特点:最快、最省资源、隔离最简单(无 Docker daemon)。
  • 不能 docker build;要产出镜像请看 kaniko / dind 两节。
  • 任意公共镜像都可用(Docker Hub / gcr.io / ghcr.io / quay.io / nvcr.io / registry.k8s.io / registry.gitlab.com 均已加速)。

kaniko

  • 只构建并推送镜像
build-image:
  stage: build
  image:
    name: martizih/kaniko:debug        # 浮动 tag,始终带 shell;等价 ghcr.io/osscontainertools/kaniko:debug
    entrypoint: [""]
  script:
    - mkdir -p /kaniko/.docker
    - |
      cat > /kaniko/.docker/config.json <<CONF
      {"auths":{"${CI_REGISTRY}":{"username":"${CI_REGISTRY_USER}","password":"${CI_REGISTRY_PASSWORD}"}}}
      CONF
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
      --destination "${CI_REGISTRY_IMAGE}:latest"
      --snapshot-mode=redo
      --compressed-caching=false
      --cache=true
      --cache-repo="${CI_REGISTRY_IMAGE}/cache"
  • 不需要特权、不需要 dind、任意 runner 都能跑。
  • 限制:不能 docker run / compose;不支持 RUN --mount=type=secret;不支持跨架构构建。
  • 缓存:--cache-repo 指向本项目 registry。
  • 关于 tag:debug 是浮动 tag(自动跟随上游最新版),不要用 latest(那是 scratch 镜像,没有 shell,CI 脚本根本跑不起来)。
  • 上游 GoogleContainerTools/kaniko 已归档(2025-06,冻结在 v1.24.0);martizih/kaniko 属于仍活跃的替代分支 osscontainertools/kaniko。

DinD

  • 在 job 里跑完整 Docker
build-and-test:
  stage: test
  tags: [dind]                     # ← 必须,否则会被派到没有 daemon 的普通 runner
  image: docker:29-cli
  services:
    - name: docker:dind
      alias: docker
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""         # 明文 2375,仅 job 内部网络
  script:
    - docker build -t myapp:ci .
    - docker run --rm myapp:ci ./run-tests.sh
    - docker compose up -d --build && docker compose ps
  • 无需 privileged(runner 侧使用隔离运行时,容器是真正的 user-namespace 隔离)。
  • 支持 docker build / run / compose,以及 docker buildx。
  • 内层 daemon 每个 job 都是全新的,镜像层不跨 job 保留;要复用请用 registry 缓存/artifacts,不要共享 docker 数据目录。
  • 想用 TLS 而不是明文:不要设 DOCKER_TLS_CERTDIR,改设 DOCKER_HOST=tcp://docker:2376、DOCKER_TLS_VERIFY=1、DOCKER_CERT_PATH=/certs/client。

自建本地 runner 并注册到 git.nju.edu.cn

什么时候用:不方便用共享 runner(需要特殊硬件、本地数据、自定义镜像环境),或想把构建放在自己的机器上。

在 GitLab 上创建 runner、拿 token

  • 位置二选一:项目 → Settings → CI/CD → Runners → New project runner。
  • 勾选 Tags,例如 myrunner —— 这是 job 匹配 runner 的唯一依据;不建议勾 "Run untagged jobs"(会跟共享 runner 抢任务)。
  • 创建后复制 runner authentication token(glrt-...,只显示一次,等同凭据,不要提交进仓库、不要写进 .gitlab-ci.yml)。

在目标机器上安装和注册 gitlab-runner

参考giblab的文档,用上一步的token注册

使用与验证

  • 只有写了 tags: [myrunner] 的 job 才会派到你的 runner。
  • GitLab → Runners 页面应显示 online;跑一条最小 job 验证即可。

命名与凭据

  • 推送目标统一用 ${CI_REGISTRY_IMAGE}(= reg.nju.edu.cn/<namespace>/<project>),不要硬编码仓库地址。
  • 拉取本项目/组内私有镜像用 $CI_JOB_TOKEN;外部 registry 凭据放 Masked + Protected 的 CI 变量。
  • 凭据不要写进 .gitlab-ci.yml,也不要 --build-arg SECRET=... 烧进镜像层(dind 可用 RUN --mount=type=secret,kaniko 不支持)。
  • Docker Hub 上游图片可走 Dependency Proxy(需要改镜像名)。