CI/CD 使用指南

先选方式

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

tags 怎么填:


常规 job

编译、构建产物、打包、测试、代码检查、部署……都属于「常规 job」:在 job 容器里跑命令、不构建镜像。它们的差别只是 stage 和 script 里跑什么;套路是 一个 job = 一个镜像 + 一串命令 +(可选)产物。

编译 / 构建产物

build:
  stage: build
  image: node:lts
  script:
    - npm ci
    - npm run build
  artifacts:
    paths: [dist/]

测试

test:
  stage: test
  image: node:lts
  needs: [build]
  script:
    - npm ci
    - npm test -- --reporter=junit --outputFile=report.xml
  artifacts:
    when: always
    reports:
      junit: report.xml

代码检查 / 静态分析

lint:
  stage: test
  image: node:lts
  script:
    - npm ci
    - npx eslint .

打包归档

package:
  stage: package
  image: alpine:latest
  needs: [build]
  script:
    - tar -czf myapp.tar.gz -C dist .
  artifacts:
    paths: [myapp.tar.gz]

用到 package 这类非默认 stage 时,要在文件顶部声明:stages: [build, test, package, deploy](GitLab 默认只有 .pre / build / test / deploy / .post)。

部署(deployment job)

部署方式很多(rsync、scp、sftp、WebDAV、对象存储、kubectl、调用发布接口……),这里只给一个最常见的例子,换传输方式只需改 script,凭据的处理方式不变。

核心原则:敏感信息(私钥、密码、Token)只放 GitLab 的 CI/CD 变量里,绝不写进仓库、.gitlab-ci.yml 或提交的文件。

deploy:
  stage: deploy
  image: alpine:latest
  variables:
    GIT_STRATEGY: none
  environment:
    name: production
    url: https://myapp.example.com
  resource_group: production
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
  before_script:
    - apk add --no-cache openssh-client rsync
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - install -m 600 "$SSH_PRIVATE_KEY" ~/.ssh/id_ed25519
    - install -m 644 "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
  script:
    - rsync -az --delete -e "ssh -i ~/.ssh/id_ed25519" dist/ deploy@my-server:/srv/myapp/
    - ssh -i ~/.ssh/id_ed25519 deploy@my-server 'cd /srv/myapp && docker compose up -d'

敏感信息存哪里(Settings → CI/CD → Variables):

变量 类型 说明
SSH_PRIVATE_KEY File 部署专用私钥(单独生成,不要用个人密钥)。File 类型下 $SSH_PRIVATE_KEY 是临时文件路径,用 install -m 600 "$SSH_PRIVATE_KEY" ~/.ssh/id_ed25519 复制,私钥内容不会出现在日志里
SSH_KNOWN_HOSTS Variable 或 File 目标机公钥指纹(ssh-keyscan my-server);不要用 StrictHostKeyChecking=no
密码 / Token Variable 勾 Masked;生产再勾 Protected(只在受保护分支的 job 里可见)

要点:


kaniko

在 job 里构建镜像并推送到 registry,不需要 Docker daemon。

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

在 job 里用完整 Docker(build / run / compose)

build-and-test:
  stage: test
  tags: [dind]                     # ← 必须,否则会被派到没有 Docker 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

自建本地 runner

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

在 GitLab 上创建 runner

在目标机器上安装注册 runner

安装与注册方式很多(Docker、deb/rpm 包、二进制、Kubernetes 等),请按你的环境选择,参考 GitLab 官方文档:

注册时 --url 填 https://git.nju.edu.cn/,--token 填上一步的 glrt-...,--executor 按需。

使用与验证


命名与凭据

常见问题


Revision #24
Created 2026-09-27 09:10:46 CST by Yao Ge
Updated 2026-09-27 10:29:10 CST by Yao Ge