Dagger TypeScript API 参考:ContainerDirectoryOpts 类型别名与 expand 环境变量展开机制
【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger
导读:本文基于 Dagger v0.20 TypeScript SDK 的 API 参考文档 ContainerDirectoryOpts.md,完整解析ContainerDirectoryOpts类型别名的唯一属性expand的语义、默认值与取值行为,并结合Container.directory()方法签名、引擎侧expandEnvVar实现与集成测试用例,说明"按容器环境变量展开路径"这一能力在 Dagger 中的底层原理与可复制用法。读完后可掌握:何时应显式传入expand、展开规则(${VAR}与$VAR两种形式)、以及对 Secret/Volatile 环境变量的硬性限制。
1. 类型定义:ContainerDirectoryOpts 是什么
原始参考文档定义了@dagger.io/dagger(即api/client.gen)模块下的类型别名:
ContainerDirectoryOpts=
object
该对象是Container.directory()方法的可选参数(opts)类型,用于控制"从容器根文件系统取回目录"这一操作对路径参数path的处理方式。文档列出的属性只有一项:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
expand? | boolean | 否(optional) | 根据容器当前定义的环境变量,替换path中的"${VAR}"或$VAR(例如"/$VAR/foo") |
对应到仓库中 TypeScript SDK 的实际类型声明(自动生成代码),定义位于 client.gen.ts:
export type ContainerDirectoryOpts = { /** * Replace "${VAR}" or "$VAR" in the value of path according to the current * environment variables defined in the container (e.g. "/$VAR/foo"). */ expand?: boolean }可以看出文档与实现完全一致:expand是唯一字段且为可选,未传入时引擎侧使用默认值false(见后文 Go schema 定义中的default:"false"标签),即默认不做任何展开,path原样使用。
2. 使用方:Container.directory() 方法签名
ContainerDirectoryOpts的唯一消费点是Container类上的directory方法,其签名(同样见 client.gen.ts)为:
/** * Retrieve a directory from the container's root filesystem * * Mounts are included. * @param path The path of the directory to retrieve (e.g., "./src"). * @param opts.expand Replace "${VAR}" or "$VAR" in the value of path according * to the current environment variables defined in the container (e.g. "/$VAR/foo"). */ directory = (path: string, opts?: ContainerDirectoryOpts): Directory => { const ctx = this._ctx.select("directory", { path, ...opts }) return new Directory(ctx) }要点:
- 返回值:同步返回一个
Directory对象(惰性求值,后续调用.file(...)、.entries()等才真正执行查询),因此可以自然嵌入管道式链式调用; - 路径语义:从容器根文件系统取目录,且文档注释明确"Mounts are included"——已挂载的目录会包含在取回结果中;
- 参数传递方式:SDK 通过
this._ctx.select("directory", { path, ...opts })把expand作为 GraphQL 查询的可选字段下发给引擎。
一个完整可运行的示例(与仓库集成测试中的场景一一对应,见 container_test.go):
import { dag } from "@dagger.io/dagger" const c = await dag() const contents = await c .container() .from("alpine:latest") .withEnvVariable("foo", "bar") .withDirectory( "/some-path/${foo}", // 目标路径同样支持展开 c.directory().withNewFile("/some-file.txt", "contents in foo file"), { expand: true } ) .directory("/some-path/${foo}", { expand: true }) // 取出 /some-path/bar .file("some-file.txt") .contents() console.log(contents) // "contents in foo file"对照 Go SDK 的写法即ctr.Directory("/some-path/${foo}", dagger.ContainerDirectoryOpts{Expand: true}),语义与字段名一一对应(expand对Expand)。
3. 引擎侧实现:expand 如何工作
在 Dagger 引擎(核心 schema 层),Container.directory对应的查询处理函数接收一个带Expand字段的参数结构体,其默认值为false,并立刻调用expandEnvVar处理路径,见 container.go:
Expand bool `default:"false"` ... path, err := expandEnvVar(ctx, parent.Self(), args.Path, args.Expand)核心展开逻辑集中在 expandEnvVar:
func expandEnvVar(ctx context.Context, parent *core.Container, input string, expand bool) (string, error) { if !expand { return input, nil // 默认不展开,路径原样返回 } cfg, err := parent.ImageConfig(ctx) // 从容器镜像配置读取环境变量 ... secretEnvs := []string{} for _, secret := range parent.Secrets { secretEnvs = append(secretEnvs, secret.EnvName) } volatileEnvs := []string{} core.WalkEnv(parent.VolatileEnv, func(name, _, _ string) { volatileEnvs = append(volatileEnvs, name) }) expanded := os.Expand(input, func(k string) string { if slices.Contains(secretEnvs, k) { secretEnvFoundError = fmt.Errorf("expand cannot be used with secret env variable %q", k) return "" } if slices.Contains(volatileEnvs, k) { secretEnvFoundError = fmt.Errorf("expand cannot be used with volatile env variable %q", k) return "" } v, _ := core.LookupEnv(cfg.Env, k) return v }) ... }从源码实现可以确认以下行为细节,这些是参考文档未展开、但对实际使用很关键的规则:
expand: false(默认)时零开销:函数直接原样返回输入,不触发任何容器状态读取;- 变量来源是容器的"已定义环境变量":实现通过
parent.ImageConfig(ctx)读取镜像配置的Env,因此只有事先通过withEnvVariable/WithEnvVariable等 API 写入容器的变量才可能被展开,而不是宿主机或引擎的环境; - 使用
os.Expand语义:Go 的os.Expand同时支持${VAR}与$VAR两种形式,与文档描述("Replace$\{VAR\}or$VAR")完全吻合;未定义的变量会被替换为空字符串; - 硬性安全限制:
expand不能用于引用 Secret 环境变量(WithMountedSecret注入的变量名)或 Volatile 环境变量,命中时直接报错expand cannot be used with secret/volatile env variable,防止敏感值被固化进路径字符串。
此外,通用入口 ExpandContainerInput 也承担了同样的"按容器环境变量展开输入字符串"职责,供需要展开的其他路径类输入复用。
4. 集成测试验证:expand 在目录 API 上的行为
仓库的集成测试对expand的目录场景做了直接验证,位于 container_test.go。其中两条用例与ContainerDirectoryOpts直接相关:
env variable is expanded in WithDirectory:先以Expand: true把目录写入/some-path/${foo}(展开为/some-path/bar),再以dagger.ContainerDirectoryOpts{Expand: true}从"/some-path/${foo}"取回该目录,最终读出文件内容断言成功;env variable is expanded in Directory:先用字面量路径/some-path/bar写入,再用ContainerDirectoryOpts{Expand: true}以"/some-path/${foo}"取出,验证"取回目录"一侧的展开。
同文件还覆盖了WithFile、File、WithMountedDirectory、WithoutDirectory等兄弟 API 的展开行为(如 L5341-L5419),说明expand是容器路径类 API 的通用能力族。
5. 同族类型:哪些 Opts 也带 expand
expand并非ContainerDirectoryOpts独有。在同一个 type-aliases 参考目录下,还有多个兄弟 Opts 类型提供相同的expand?属性,例如:
- ContainerFileOpts.md —
Container.file()的路径展开; - ContainerExistsOpts.md —
Container.exists()的路径展开(该类型额外含expectedType?与doNotFollowSymlinks?); - ContainerWithDirectoryOpts.md — 写入目录一侧的路径展开。
引擎侧也印证了这一点:在 core/schema/container.go 中,expandEnvVar被WithFile、WithDirectory、WithMountedFile、File、WithoutDirectory等十余个查询处理函数复用,每次都以Expand bool \default:"false"`` 的形式出现,说明这是引擎对"容器内路径字符串"的统一处理约定。
6. 使用建议与适用前提
基于上述文档与源码证据,给出可操作的使用要点:
- 何时需要
expand: true:当目标目录路径依赖容器内动态确定的值(如通过withEnvVariable设置的构建产物子目录)时,在directory()调用中传入{ expand: true };若路径是静态字面量,省略该参数即可,行为完全一致且避免不必要的状态读取; - 两种变量写法都支持:
"/builds/${BUILD_ID}"与"/builds/$BUILD_ID"均可,但建议统一使用花括号形式以避免相邻标识符造成的歧义; - 不要依赖宿主环境:
expand只解析容器自身ImageConfig中的环境变量,宿主机 shell 变量不会进入展开范围; - 避免引用 Secret 变量:将 Secret 挂载为环境变量后,若路径字符串中出现同名变量,
expand会直接报错而非静默替换,这是设计上的安全边界; - 版本前提:本文基于 version-0.20 API 参考与当前仓库的 TypeScript SDK 生成代码(client.gen.ts);该类型由 Dagger 的 GraphQL schema 经 codegen 生成,后续版本中新增字段(若有)以对应版本的参考文档为准。
参考路径汇总
| 内容 | 路径 |
|---|---|
| 原始 API 参考文档(本文主体) | ContainerDirectoryOpts.md |
| TS SDK 类型与方法生成代码 | sdk/typescript/src/api/client.gen.ts |
| 引擎侧目录查询与展开调用 | core/schema/container.go |
| 展开核心实现 | expandEnvVar |
| 通用展开入口 | core/container.go |
| 集成测试验证 | core/integration/container_test.go |
【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考