---
url: /en/build/create-plugin.md
description: >-
  Step-by-step guide for developing a Cloud Native Build plugin as a Docker
  image, covering parameter design, input handling, image building, and
  publishing to the plugin registry.
---
In `Cloud Native Build`, a plugin is essentially a Docker image.
Below is how to develop an image plugin from scratch using Bash.

This example plugin prints `hello world`. We assume you have basic knowledge of Docker.

## Designing the Plugin

### Parameter Design

Design the plugin parameters:

* `text`: The text content to be printed to the console

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: hello world
          image: cnbcool/hello-world
          settings:
            text: hello world
```

These parameters are passed to the container as environment variables, converted to uppercase with a `PLUGIN_` prefix.

The above parameters will be transformed into the following environment variables:

```text
PLUGIN_TEXT="hello world"
```

### Supported Parameter Types

Parameter types support `string`, `number`, `boolean`, `one-dimensional array`, and `plain object`.

Where:

* Arrays will be split by commas `,` when passed to the container
* Plain objects will be converted to JSON strings when passed to the container

If parameters are overly complex, consider storing them in a file and loading at runtime,
simplifying the design, or splitting into multiple plugins.

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

Corresponding environment variables:

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

## Writing the Script

Next, write a Bash script to print the parameters:

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

## Building the Plugin Image

The plugin is packaged as a `Docker` image for distribution.
Create a `Dockerfile` to package the script and set it as the `Entrypoint`.

```bash
FROM alpine

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

ENTRYPOINT /bin/entrypoint.sh
```

Build the image:

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

## Testing the Plugin

Test the plugin locally using `docker run`, passing parameters via environment variables:

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

### Testing Filesystem Access

The plugin can read the build process workspace directory. By default,
the build directory is mapped to a plugin directory and set as the workspace:

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

## Exporting Variables

If the plugin needs to return results and export them as variables for subsequent tasks, refer to [exports](./grammar.md#job-exports)

## Publishing the Plugin

A plugin is a Docker image — publishing a plugin means publishing the image.

You can publish to the built-in
[Artifact Registry](../artifact/docker.md) of Cloud Native Build,
or to Docker Hub for global availability.

### Pushing the Image

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