stage 自定义挂载卷使用说明
分享链接
作者 :Gitfox
最后编辑:孟笑宇 于 2026-11-13 14:02:10
阅读:24
流水线卷挂载 YAML 配置说明(volumes / mount)
本文说明如何在流水线 YAML 中声明卷(volumes)以及在任务上挂载卷(mount),包括 plugin 任务的挂载合并规则、内置工作区注意事项和常见报错。
背景
流水线中每个 step 都运行在独立容器里,构建结束即销毁,默认只有内置的 _workspace 卷用于共享克隆下来的源码。用户无法声明自己的卷,也就无法在任务之间共享数据,或把依赖缓存保留到下一次构建。
为此引入两级声明:
- 阶段级
volumes:声明卷的名称、类型和来源; - 任务级
mount:把已声明的卷挂载到当前容器目录。
同一个卷可以被多个任务挂到不同路径。运行时按声明顺序解析卷。
解决的问题
- 任务间数据不共享:每个 step 是独立容器,把同一卷挂到多个 step,即可传递构建产物或已下载的依赖。
- 依赖无法跨构建复用:使用
host卷把依赖缓存留在宿主机,下次构建直接命中,省去重复下载。 - 配置/凭据注入:把配置文件挂进容器,无需写死在镜像里。
- 安全隔离:保留卷名和挂载路径校验,防止覆盖内置卷或工作区,避免错误挂载被静默忽略。
使用手册
1. 基本结构
卷在 CI stage 的 spec.volumes 中声明,然后在 step 的 spec.mount 中按名字引用:
stages:
- type: ci
spec:
volumes:
- name: cache # 卷名,stage 内唯一
type: temp # host / temp
steps:
- name: 写入
type: run
spec:
mount:
- name: cache
path: /cache
script:
- echo hello > /cache/hello.txt
- name: 读取
type: run
spec:
mount:
- name: cache
path: /cache
script:
- cat /cache/hello.txt
要点:
volumes是 stage 级的,只能在type: ci的 stage 中声明;同一个 stage 的所有任务共享这些卷,跨 stage 不共享。mount是 step 级的,写在 step 的spec下。- 卷通过
name关联,path是容器内的挂载路径。
2. 卷定义:volumes
volumes:
- name: <卷名>
type: host | temp
spec:
...
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 卷名,stage 内唯一;不能使用保留名(见下) |
type |
是 | 当前运行器仅支持 host、temp |
spec |
视类型 | host / temp 各自的配置 |
2.1 type: host
把宿主机目录挂进容器。
volumes:
- name: m2
type: host
spec:
path: /data/gitfox/m2 # 宿主机上的绝对路径
| 字段 | 说明 |
|---|---|
spec.path |
宿主机目录路径 |
2.2 type: temp
由运行器创建临时卷,stage 结束后清理。
volumes:
- name: tmp
type: temp
2.3 保留卷名
以下名字由运行器内部使用,用户不能声明:
_workspace _addons _docker_socket socketDir
声明后会报错:
stage volume name "_workspace" is reserved
3. 挂载:mount
steps:
- name: 自定义脚本
type: run | plugin
spec:
mount:
- name: <卷名>
path: <容器内绝对路径>
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 引用的卷名,必须在本 stage 的 volumes 中声明 |
path |
是 | 容器内挂载路径,必须以 / 开头 |
规则:
- 同一个卷可以挂到多个任务、也可以在同一容器内挂到多个路径。
- 同一任务内挂载路径不能重复;路径会先做规范化(
path.Clean),因此/data/、/a/../data和/data视为同一个路径,重复会报错。
4. 跨任务共享示例
stages:
- type: ci
spec:
volumes:
- name: tmp
type: temp
steps:
- name: git克隆
type: plugin
spec:
name: scm_git_clone
mount:
- name: tmp
path: /gitfox
inputs:
...
- name: 自定义脚本
type: run
spec:
mount:
- name: tmp
path: /tmp
script:
- ls -l /tmp
第一步把内容写进 tmp 卷的 /gitfox,第二步在 /tmp 能看到同一份数据。
5. 内置工作区 /gitfox 与挂载冲突
每个任务默认会追加一个内置工作区挂载:
_workspace -> /gitfox
如果某个任务显式把用户卷挂到了 /gitfox:
- 用户挂载优先,内置工作区挂载会被跳过,并输出一条 warn 日志;
- 该任务里的
/gitfox是用户卷,不再与其他任务共享工作区内容(除非其他任务也挂同一个卷); GITFOX_WORKSPACE环境变量仍然是/gitfox,插件仍会往这个路径写;- stage 末尾的 clean 任务会操作用户挂载的工作区。
如果你希望多个任务共享同一目录,推荐显式声明一个 temp/host 卷,并在各任务挂载到同一路径:
stages:
- type: ci
spec:
volumes:
- name: shared
type: temp
steps:
- name: 写入
type: run
spec:
mount:
- name: shared
path: /data
script:
- echo hi > /data/a.txt
- name: 读取
type: run
spec:
mount:
- name: shared
path: /data
script:
- cat /data/a.txt
最佳实践: 编译缓存,构建提速
将编译过程中的依赖缓存在宿主机中,下次构建直接命中,省去重复下载时间,提高编译效率
golang 编译缓存
version: 1
kind: pipeline
spec:
options:
clone:
disabled: true
stages:
- id: 0kjuhvvc
name: 阶段
desc: ''
type: ci
when: ${{ success() }}
spec:
# 1. 阶段层声明卷:宿主机目录,跨构建保留
volumes:
- name: cache
type: host
spec:
path: /root/tmp/go-cache
steps:
- id: wnrv8ek5_scm_git_clone
when: ${{ success() }}
name: git克隆
type: plugin
spec:
inputs:
repository: http://example.com:3000/git/test/go-repo.git
gitRef: ${{parameters.gitRef}}
cloneDepth: 1
cloneDir: ''
name: scm_git_clone
- id: r889y3o3_build_go
when: ${{ success() }}
name: Golang编译
type: plugin
spec:
# 2. 编译任务挂到 Go 模块缓存目录
mount:
- name: cache
path: /root/.gvm/pkgsets/go1.26.2/global/pkg/mod # go modules存放目录,挂载至宿主机目录
inputs:
compileCommand: pwd && export GOPROXY=https://goproxy.cn,direct && go mod tidy
workspace: .
goVersion: 1.26.2
name: build_go
6.2 编译提速效果
| 编译时长 | 是否有缓存 | 提速 |
|---|---|---|
| 20s | 无 | |
| 3s | 有 | 快6.7倍 |
6.3 其他语言缓存目录参考
| 语言 | 建议挂载路径 | 相关环境变量 |
|---|---|---|
| Go | $GOPATH/pkg/mod | GOMODCACHE |
| NodeJs | ~/.npm | npm_config_cache |
| Python | ~/.cache/pip | PIP_CACHE_DIR |
| Maven | ~/.m2/repository | - |
常见问题
挂载声明会在两处校验:
- 触发流水线时:解析、插件/模板展开之后校验,错误直接返回给触发方,不生成 stage/step 记录;
- 运行器编译时:
CompilerImpl.Compile开头再次校验,作为最终校验。
常见错误:
| 报错 | 原因 |
|---|---|
stage volume #1: name must not be empty |
volumes 项缺少 name |
stage volume name "_workspace" is reserved |
使用了保留卷名 |
stage volume "cache" is declared more than once |
同 stage 内卷名重复 |
stage volume "cache": volume type "claim" is not supported |
使用了不支持的卷类型 |
step "build": mount must not be empty |
mount 列表里有空项 |
step "build": mount path must be absolute: "data" |
挂载路径不是绝对路径 |
step "build": duplicate mount path "/data" |
同一任务内路径重复(规范化后) |
step "build": mount path "/data" requires a volume name |
mount 缺少 name |
step "build": mount volume "data" is not declared in stage volumes |
引用了未声明的卷名 |
step "git克隆": resolved plugin step type "group" does not support mount |
插件展开后的类型不支持挂载 |
触发阶段的错误会带上 stage 上下文,例如:
stage "stage-1": step "build": mount volume "data" is not declared in stage volumes