---
url: /zh/build/create-plugin.md
description: 介绍如何从零开发一个云原生构建 Docker 镜像插件，包括参数设计、Dockerfile 编写和插件发布流程。
---
在 `云原生构建` 中，一个插件就是一个 Docker 镜像。下面以 Bash 为例，介绍如何从零开发一个镜像插件。

本示例插件的功能是打印 `hello world`，阅读前需了解 Docker 基础知识。

## 设计插件

### 参数设计

设计插件参数：

* `text`: 要输出到控制台的文本内容

### 支持的参数类型

参数类型支持`字符串`、`数值`、`布尔值`、`一维数组`、`普通对象`。

其中：

* 数组传给容器时以英文逗号 `,` 分隔
* 普通对象传给容器时会转为 JSON 字符串

如果参数结构过于复杂，建议存放到文件中由插件运行时加载，
或简化参数设计、拆分为多个插件。

配置示例：

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: hello world
          image: cnbcool/hello-world
          settings:
            text: hello world
            boolean: true
            number: 123
            array: [hello, world]
            map:
              key: value
```

这些参数会转换为大写并添加 `PLUGIN_` 前缀，以环境变量的形式传入容器：

```text
PLUGIN_TEXT='hello world'
PLUGIN_BOOLEAN='true'
PLUGIN_NUMBER='123'
PLUGIN_ARRAY='hello,world'
PLUGIN_MAP='{"key":"value"}'
```

## 编写脚本

编写 Bash 脚本打印参数：

```bash
#!/bin/sh
echo "$PLUGIN_TEXT"
```

## 构建插件镜像

插件会打包成 `Docker` 镜像分发使用。
需要创建一个 `Dockerfile` 将脚本打包进去，并设置为 `Entrypoint`。

```bash
FROM alpine

ADD entrypoint.sh /bin/
RUN chmod +x /bin/entrypoint.sh

ENTRYPOINT /bin/entrypoint.sh
```

构建镜像：

```bash
docker build -t cnbcool/hello-world .
```

## 测试插件

建议在本地测试插件，使用 `docker run` 运行，通过环境变量传入参数：

```bash
docker run --rm \
  -e PLUGIN_TEXT="hello world" \
  cnbcool/hello-world
```

### 测试文件系统访问

插件可以读取构建流程工作区目录，
默认将构建目录映射到插件的某个目录并设置为工作区：

```bash
docker run --rm \
  -e PLUGIN_TEXT="hello world" \
  -v $(pwd):$(pwd) \
  -w $(pwd) \
  cnbcool/hello-world
```

## 导出变量

插件执行完成后，可以通过 `##[set-output key=value]` 格式输出结果，
再配合流水线的 [`exports`](./grammar.md#job-exports) 将其导出为环境变量，供后续任务使用。

### 示例：导出 GREETING 变量

假设插件需要将 `hello world` 导出为变量 `GREETING`，供后续 Job 使用。

**1. 修改插件脚本，输出自定义变量：**

```bash title="entrypoint.sh"
#!/bin/sh
echo "$PLUGIN_TEXT"

# 输出自定义变量，供 exports 导出
printf '##[set-output greeting=%s]\n' "$PLUGIN_TEXT"
```

> `##[set-output key=value]` 会被 CI 解析到 Job 的 `result` 对象中，之后可通过 `exports` 导出为环境变量。

**2. 在流水线中使用 `exports` 导出变量，并在后续任务中引用：**

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: hello world
          image: cnbcool/hello-world
          settings:
            text: hello world
          exports:
            greeting: GREETING
        - name: use greeting
          script: echo $GREETING
```

运行后，第二个 Job 会输出 `hello world`。

::: tip 更多用法
`exports` 支持导出脚本执行结果（`code`、`stdout`、`stderr`、`info`）
和内置任务返回值，详见 [环境变量 - 导出环境变量](./env.md#导出环境变量)。
:::

## 发布插件

插件是一个 Docker 镜像，发布插件即发布镜像。

可发布到云原生构建仓库自带的 [制品库](../artifact/docker.md)，
也可发布到 Docker Hub 以供全球使用。

### 发布镜像

```bash
docker push cnbcool/hello-world
```
