跳到主要内容

高级用法

高级 YAML 语法

YAML 有一些高级语法功能,可以像变量一样使用,以减少管道配置中的重复:

锚点和别名

您可以在管道配置中使用 YAML 锚点和别名 作为变量。

要转换这个:

steps:
- name: test
image: golang:1.18
commands: go test ./...
- name: build
image: golang:1.18
commands: build

只需添加一个名为 variables 的新部分,如下所示:

+variables:
+ - &golang_image 'golang:1.18'

steps:
- name: test
- image: golang:1.18
+ image: *golang_image
commands: go test ./...
- name: build
- image: golang:1.18
+ image: *golang_image
commands: build

映射合并和覆盖

variables:
- &base-plugin-settings
target: dist
recursive: false
try: true
- &special-setting
special: true
- &some-plugin codeberg.org/6543/docker-images/print_env

steps:
- name: develop
image: *some-plugin
settings:
<<: [*base-plugin-settings, *special-setting] # 将两个映射合并到空映射中
when:
branch: develop

- name: main
image: *some-plugin
settings:
<<: *base-plugin-settings # 合并一个映射并且...
try: false # ... 覆盖原始值
ongoing: false # ... 添加新值
when:
branch: main

序列合并

variables:
pre_cmds: &pre_cmds
- echo start
- whoami
post_cmds: &post_cmds
- echo stop
hello_cmd: &hello_cmd
- echo hello

steps:
- name: step1
image: debian
commands:
- <<: *pre_cmds # 前置一个序列
- echo exec step now do dedicated things
- <<: *post_cmds # 追加一个序列
- name: step2
image: debian
commands:
- <<: [*pre_cmds, *hello_cmd] # 前置两个序列
- echo echo from second step
- <<: *post_cmds

参考资料

在步骤之间持久化环境数据

可以创建一个包含环境变量的文件,然后在每个需要它们的步骤中引用它。

steps:
- name: init
image: bash
commands:
- echo "FOO=hello" >> envvars
- echo "BAR=world" >> envvars

- name: debug
image: bash
commands:
- source envvars
- echo $FOO

声明全局变量

全局环境变量中所述,您可以定义全局变量:

WOODPECKER_ENVIRONMENT=first_var:value1,second_var:value2

请注意,这会紧密耦合服务器和应用程序配置(其中应用程序是完全独立的应用程序)。但这对于应该应用于所有应用程序的所有管道中的所有步骤的真正全局变量来说是一个好选择。

Docker in docker (dind) 设置

注意

此设置仅适用于受信任的仓库,出于安全原因应仅在私有环境中使用。 请参阅项目设置以启用"受信任"模式。

下面的代码片段展示了步骤如何与运行在 docker:dind 服务中的 docker 守护进程通信。

备注

如果您的目标是构建/发布 OCI 镜像,请考虑使用 Docker Buildx 插件 代替。

首先我们需要定义一个运行带有 dind 标签的 docker 的服务。 此服务必须在 privileged 模式下运行:

services:
- name: docker
image: docker:dind # 在生产中使用 'docker:<major-version>-dind' 或类似版本
privileged: true
ports:
- 2376

接下来,我们需要在 dind 服务和想要与 docker 守护进程通信的步骤之间设置 TLS 通信(未认证的 TCP 连接自 docker v27 起已被废弃,并将在 v28 中导致错误)。

这可以通过让守护进程生成 TLS 证书并通过代理卷挂载(下面示例中的 /opt/woodpeckerci/dind-certs)与客户端共享它们来实现。

services:
- name: docker
image: docker:dind # 在生产中使用 'docker:<major-version>-dind' 或类似版本
privileged: true
+ environment:
+ DOCKER_TLS_CERTDIR: /dind-certs
+ volumes:
+ - /opt/woodpeckerci/dind-certs:/dind-certs
ports:
- 2376

在 docker 客户端步骤中:

  1. 设置下面显示的 DOCKER_* 环境变量以配置与守护进程的连接。 这些是框架无关的通用 docker 环境变量(例如,TestContainersSpring Boot Docker Compose 等框架都会遵循它们)。
  2. 将卷挂载到守护进程创建证书的位置(/opt/woodpeckerci/dind-certs

使用 docker 客户端测试连接:

steps:
- name: test
image: docker:cli # 在生产中使用类似 'docker:<major version>-cli' 的版本
+ environment:
+ DOCKER_HOST: "tcp://docker:2376"
+ DOCKER_CERT_PATH: "/dind-certs/client"
+ DOCKER_TLS_VERIFY: "1"
+ volumes:
+ - /opt/woodpeckerci/dind-certs:/dind-certs
commands:
- docker version

如果一切设置正确,此步骤应输出服务器和客户端版本信息。

完整示例:

steps:
- name: test
image: docker:cli # 在生产中使用 'docker:<major-version>-cli' 或类似版本
environment:
DOCKER_HOST: 'tcp://docker:2376'
DOCKER_CERT_PATH: '/dind-certs/client'
DOCKER_TLS_VERIFY: '1'
volumes:
- /opt/woodpeckerci/dind-certs:/dind-certs
commands:
- docker version

services:
- name: docker
image: docker:dind # 在生产中使用 'docker:<major-version>-dind' 或类似版本
privileged: true
environment:
DOCKER_TLS_CERTDIR: /dind-certs
volumes:
- /opt/woodpeckerci/dind-certs:/dind-certs
ports:
- 2376