---
url: /en/build/create-plugin.md
---
In `Cloud Native Build`, a plugin is essentially a `Docker` image.
Here we'll demonstrate how to develop an image plugin from scratch using `Bash`.
This plugin's functionality is to print `hello world`.
This guide should provide you with a clear approach to creating your own plugins.
We assume you already have some basic knowledge of `Docker`.

## Designing the Plugin

### Parameter Design

The first step is to design the parameters required by the plugin:

* `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 input parameters will be passed to the container as environment variables, with the difference that they will be converted to uppercase and prefixed with `PLUGIN_`.

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

For example:

```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
```

The parameter values will be transformed into the following environment variables:

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

For particularly complex parameter values, they can be stored in a file and loaded when the plugin runs.
If you encounter extremely complex parameter values, it's often not a format issue - you should simplify these parameters or split them into multiple plugins.

## Writing the Script

Next, write a Bash script to print the parameters, as shown below:

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

## Building the Plugin Image

The plugin will be packaged as a `Docker` image for distribution and use.
Therefore, we need to create a `Dockerfile` to package our previously written 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 your image:

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

## Testing the Plugin

You should test your plugin locally, using `docker run` to execute the plugin and pass parameters via environment variables:

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

### Testing Filesystem Access

The plugin has permission to read your build process workspace directory. It will map the build directory to a specific directory in the plugin by default and set this directory 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, so publishing a plugin means pushing the image to an image registry.

You can publish to the built-in [Artifact Registry](../artifact/docker.md) of `Cloud Native Build`.

For globally available plugins, you can also publish to `Docker Hub`.

### Pushing the Image

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