---
url: /en/build/build-env.md
---
## 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 runtime for the build environment. Compared to traditional virtual machines, Docker containers offer significant advantages including faster startup times, lower resource overhead, and superior environment consistency, making them the industry standard for modern CI/CD.

::: 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 for your pipeline 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 that has been pushed to a container registry (e.g., Docker Hub, private registry). This is the fastest method.

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

### Build Image Dynamically (build)

Specify a `Dockerfile` file within your project. At the start of the build, the system will dynamically build an image based on this file for use in subsequent steps.

**Mechanism**:

1. The system first calculates a hash value for the image version
2. If an image with this hash already exists in the local cache or remote registry, it is used directly, significantly speeding up the build process
3. Otherwise, it executes `docker build` to create the image, and automatically pushes it to the artifact repository associated with the pipeline project for reuse in subsequent builds

**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 its **script tasks**.

Furthermore, each **script task** can override this and 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.
:::
