---
url: /en/build/build-env.md
description: >-
  Explains how to configure the Docker-based build environment for Cloud Native
  Build pipelines, covering how to use existing images or build images
  dynamically from a Dockerfile.
---
## Overview

The build environment defines the runtime environment for pipeline jobs,
containing all the software and tools required for execution, such as specific versions of JDK, Node.js, Python, etc.

`Cloud Native Build` uses Docker containers as the build runtime. Compared to traditional virtual machines,
Docker containers offer faster startup, lower resource overhead, and better environment consistency,
making them the CI/CD industry standard.

::: tip
Having a basic understanding of Docker will help you better comprehend and utilize `Cloud Native Build`.
:::

## Configuration Methods

You can configure the build environment in the following two ways:

| Configuration Method | Description | Use Case | Permission Requirements |
|---------------------|-------------|----------|------------------------|
| [Use Existing Image (`image`)](#example-1-using-existing-image-image) | Directly use a pre-built image that has been pushed to a container registry | Using official images or team-internal pre-configured public tool images | Private images require registry authentication configuration |
| [Build Image Dynamically (`build`)](#example-2-building-image-with-dockerfile-build) | Specify a Dockerfile in the project to dynamically build an image | Complex projects requiring highly customized environments, specific dependencies, or tools | No special requirements |

### Use Existing Image (image)

Directly use a pre-built image pushed to a container registry. This is the quickest method.

**Syntax Reference**: [`pipeline.docker.image`](./grammar.md#pipeline-image)

### Build Image Dynamically (build)

Specify a `Dockerfile` in the project to dynamically build an image at the start of the build.

**Mechanism**:

1. The system calculates a hash value for the image version
2. If the image exists in the local cache or remote registry, it is used directly, speeding up the build
3. Otherwise, `docker build` is executed to create the image,
   which is automatically pushed to the project's artifact registry for reuse

**Syntax Reference**: [`pipeline.docker.build`](./grammar.md#pipeline-build)

### Environment Scope

The build environment declared at the pipeline level serves as the default runtime environment for all **script
tasks**. Each **script task** can also specify its own `image` environment.

::: warning
Task-level configuration only supports `image`, not `dockerfile`.
:::

**Syntax Reference**: [Script Task](./grammar.md#job-script-task)

## Examples

### Example 1: Using Existing Image (image)

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        # Declare the official Node.js 22 image as the default build environment for the pipeline
        image: node:22
      stages:
        # The following script tasks will run in the node:22 environment
        - node -v # Output: v22.x.x
```

### Example 2: Building Image with Dockerfile (build)

**Step 1**: Create a Dockerfile

```dockerfile title="image/Dockerfile"
# Build a custom environment based on Node.js 20
FROM node:20
# You can install more project-specific global dependencies here
# RUN npm install -g yarn
```

**Step 2**: Configure the pipeline to use this Dockerfile

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        # Declare to use the project's Dockerfile to build the environment image
        build: image/Dockerfile
      stages:
        # The following script tasks will run in the custom-built environment
        - node -v # Output: v20.x.x
```

### Example 3: Overriding Environment at Task Level

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        # Pipeline default environment
        image: node:22
      stages:
        - node -v # Output: v22.x.x (Uses default environment)
        - name: Task using a specific image version
          image: node:20 # This task overrides and uses Node.js 20
          script:
            - node -v # Output: v20.x.x
```

### Example 4: Using Default Images

When a pipeline does not explicitly specify any `image` or `build` configuration,
the system automatically uses a default image to ensure a basic environment is available.

**Default Image Configuration**:

| Build Type | Default Image Variable |
|-----------|----------------------|
| Cloud Native Build | `cnbcool/default-build-env` |
| Cloud Native Development | `cnbcool/default-dev-env` |

**Cloud Native Build Example**:

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - stage1
        - stage2
# The above configuration is equivalent to:
# docker:
#   image: cnbcool/default-build-env
```

**Cloud Native Development Example**:

```yaml title=".cnb.yml"
main:
  vscode:
    - services:
        - vscode
      stages:
        - stage1
        - stage2
# For Cloud Native Development without a specified environment, equivalent to:
# docker:
#   image: cnbcool/default-dev-env
```

## Volume Sharing

If your custom image declares data volumes using the `VOLUME` instruction (e.g., `VOLUME /cache`),
these volumes are automatically shared with containers started by subsequent **plugin tasks**.

### Application Example

**Step 1**: Prepare shared data in the Dockerfile

```dockerfile
FROM alpine
RUN mkdir /cache && echo 'Initial data' > /cache/data.txt
VOLUME /cache # Declare /cache as a data volume
```

**Step 2**: Access the shared data in a subsequent task

```yaml
- name: Read data from the shared volume
  image: alpine # A task using a different image
  script:
    - cat /cache/data.txt # Successfully outputs: Initial data
```

::: tip
Volume sharing allows different image tasks to share data,
making it ideal for scenarios like caching dependencies and sharing build artifacts.
:::
