> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build with Buildpacks

> Build container images without Dockerfiles using Cloud Native Buildpacks.

[Cloud Native Buildpacks](https://buildpacks.io) automatically detect your application language and create an optimized container image without writing a Dockerfile. They handle dependency installation, compilation, and runtime configuration based on conventions for each language.

## Quick Start

Build and push an image using buildpacks:

```bash theme={null}
cpln image build --name my-app:v1 --push
```

If your project has no Dockerfile, the CLI will install [pack](https://buildpacks.io/docs/tools/pack/) (if not already available) and use `pack build` under the hood. All buildpack-related flags are passed directly to pack.

## Build Options

| Flag                       | Description                                                             |
| -------------------------- | ----------------------------------------------------------------------- |
| `--builder`, `-B`          | CNB-compatible builder image (default: `heroku/builder:24`)             |
| `--buildpack`, `-b`        | Additional buildpack to use (can be specified multiple times)           |
| `--dir`                    | Build context directory (default: current directory)                    |
| `--push`                   | Push the image to your org's private registry after building            |
| `--no-cache`               | Build without using cache                                               |
| `--env`, `-e`              | Environment variable for the build (can be specified multiple times)    |
| `--env-file`               | File containing environment variables (can be specified multiple times) |
| `--trust-builder`          | Trust the builder image (skip security prompts)                         |
| `--trust-extra-buildpacks` | Trust additional buildpacks                                             |
| `--platform`, `-p`         | Target platform (default: `linux/amd64`)                                |

## Common Builders

| Builder                               | Description                                                      |
| ------------------------------------- | ---------------------------------------------------------------- |
| `heroku/builder:24`                   | Default. Supports Node.js, Python, Go, Java, Ruby, PHP, and more |
| `gcr.io/buildpacks/builder:google-22` | Google Cloud buildpacks                                          |
| `paketobuildpacks/builder-jammy-base` | Paketo community buildpacks (includes .NET, Rust support)        |

## Language Conventions

The following conventions apply to the default `heroku/builder:24` unless otherwise noted. Other builders may have different requirements.

<AccordionGroup>
  <Accordion title="Node.js">
    **Required files:**

    * `package.json` in the project root
    * `package-lock.json` in the project root

    <Warning>
      Run `npm install` before building to ensure `package-lock.json` is up to date with your dependencies.
    </Warning>

    **Start command:**

    * If `index.js` or `server.js` exists in the root, it will be used automatically
    * Otherwise, add a `scripts.start` command in `package.json`
    * Alternatively, create a `Procfile` in the project root

    **Example Procfile:**

    ```
    web: node src/app.js
    ```

    **Example package.json (with start script):**

    ```json theme={null}
    {
      "name": "my-app",
      "scripts": {
        "start": "node src/app.js"
      },
      "engines": {
        "node": "20.x"
      }
    }
    ```

    **Example package.json (with index.js or server.js in root):**

    ```json theme={null}
    {
      "name": "my-app",
      "engines": {
        "node": "20.x"
      }
    }
    ```

    <Tip>
      Specify your Node.js version in `engines.node` to ensure consistent builds.
    </Tip>
  </Accordion>

  <Accordion title="Python">
    **Detection (required - one of):**

    * `requirements.txt` (pip)
    * `uv.lock` (uv)
    * `poetry.lock` (Poetry)

    These files are used to detect a Python app and install dependencies.

    **Extra requirements:**

    * Using **uv** requires a `.python-version` file
    * Using **Poetry** for a non-packaged app requires `package-mode = false` in `pyproject.toml`

    **Start command (required for web apps):**

    * Create a `Procfile` in the project root
    * Python buildpacks do **not** auto-detect an entry file
    * Without a `Procfile`, the app may build but will not start

    **Example Procfile:**

    ```
    web: gunicorn -b 0.0.0.0:$PORT app:app
    ```

    **Runtime requirements:**

    * Server must bind to `0.0.0.0`
    * Server must listen on `$PORT`

    **Example requirements.txt:**

    ```
    flask==3.0.0
    gunicorn==21.2.0
    ```
  </Accordion>

  <Accordion title="Go">
    **Required files:**

    * `go.mod` in the project root

    **Project structure:**

    * The `main` package must be in the project root

    **Build behavior:**

    * Compiles the `main` package
    * Binary is automatically set as the start command

    **Example go.mod:**

    ```
    module github.com/myorg/myapp

    go 1.21
    ```
  </Accordion>

  <Accordion title="Java (Maven)">
    **Required files:**

    * `pom.xml` in the project root

    **Build behavior:**

    * Runs `mvn package`

    **Start command:**

    * Spring Boot JARs: start command is auto-detected
    * Non-Spring executable JARs: add a `Procfile` (recommended)

    **Runtime requirements:**

    * Server must bind to `0.0.0.0`
    * Server must listen on `$PORT`

    <Tip>
      If you need a specific JDK version, pin it explicitly (otherwise the builder default may be used).
    </Tip>

    **Example pom.xml excerpt (Spring Boot):**

    ```xml theme={null}
    <packaging>jar</packaging>
    <build>
      <plugins>
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
      </plugins>
    </build>
    ```
  </Accordion>

  <Accordion title="Java (Gradle)">
    **Required files:**

    * `build.gradle` or `build.gradle.kts` in the project root
    * `gradlew` (Gradle Wrapper) in the project root

    **Build behavior:**

    * Runs `./gradlew build`

    **Start command:**

    * Spring Boot JARs: start command is auto-detected
    * Non-Spring executable JARs: add a `Procfile` (recommended)

    **Runtime requirements:**

    * Server must bind to `0.0.0.0`
    * Server must listen on `$PORT`

    <Tip>
      If you need a specific Java version, add `system.properties` (e.g. `java.runtime.version=21`).
      Avoid Gradle toolchains unless you configure toolchain downloads.
    </Tip>
  </Accordion>

  <Accordion title="Ruby">
    **Required files:**

    * `Gemfile` and `Gemfile.lock` in the project root

    **Start command:**

    * Rails apps: default start command exists, but a `Procfile` is recommended
    * Non-Rails apps: create a `Procfile` with `web: <command>`

    **Runtime requirements:**

    * Server must listen on `$PORT`

    **Example Procfile (non-Rails):**

    ```
    web: bundle exec puma -p $PORT config.ru
    ```

    **Example Procfile (Rails with Puma):**

    ```
    web: bundle exec puma -C config/puma.rb
    ```
  </Accordion>

  <Accordion title="PHP">
    **Required files:**

    * `composer.json` and `composer.lock` in the project root

    **Start command:**

    * Create a `Procfile` with `web: <command>`

    **Example Procfile (Apache):**

    ```
    web: heroku-php-apache2 public/
    ```
  </Accordion>

  <Accordion title="Rust">
    Rust is not supported by the default `heroku/builder:24`. Use the Paketo Community Rust buildpack.

    **Required files:**

    * `Cargo.toml` in the project root
    * `Cargo.lock` in the project root
    * A binary target (e.g. `src/main.rs` or `src/bin/*.rs`)

    **Build command:**

    ```bash theme={null}
    cpln image build --name my-rust-app:v1 --push -b docker.io/paketocommunity/rust
    ```

    **Build behavior:**

    * Builds the project using `cargo build --release`
    * The resulting binary is used as the default launch command (or can be overridden via a Procfile)

    **Example Cargo.toml:**

    ```toml theme={null}
    [package]
    name = "my-app"
    version = "0.1.0"
    edition = "2021"

    [dependencies]
    actix-web = "4"
    ```

    **Process configuration (optional):**

    ```procfile theme={null}
    web: my-app
    ```

    > Note: The binary name is derived from `[package].name` and must match the Procfile entry exactly.

    **Runtime requirements:**

    * Server must listen on `$PORT` (read from environment variable)
  </Accordion>

  <Accordion title="C# / .NET">
    C# / .NET is not supported by the default `heroku/builder:24`. Use the Paketo .NET buildpacks via a Paketo builder.

    **Required files:**

    * A `.csproj` or `.fsproj` file in the project root, or
    * A `.sln` file with referenced projects

    **Build command:**

    ```bash theme={null}
    cpln image build --name my-dotnet-app:v1 --push -B paketobuildpacks/builder-jammy-base
    ```

    **Build behavior:**

    * Runs `dotnet publish` (Release)
    * Automatically detects the entry point DLL for single-project apps

    **Start command:**

    * Auto-detected for single-project solutions
    * Optional: add a `Procfile` to explicitly set or override the start command (recommended for multi-project solutions)

    **Example .csproj:**

    ```xml theme={null}
    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>net9.0</TargetFramework>
      </PropertyGroup>
    </Project>
    ```

    **Example Procfile (optional):**

    ```
    web: dotnet MyApp.dll
    ```

    **Runtime requirements:**

    * Server must bind to `0.0.0.0` (not `127.0.0.1`)
    * Server must listen on `$PORT` (recommended: set `ASPNETCORE_URLS` to `http://0.0.0.0:$PORT`)

    <Tip>
      The simplest way to ensure correct port binding is to set `ASPNETCORE_URLS` in your workload:

      ```
      ASPNETCORE_URLS=http://0.0.0.0:$PORT
      ```
    </Tip>
  </Accordion>
</AccordionGroup>

## The Procfile

A `Procfile` defines how your application is started by the platform. Place it in the project root.

```text theme={null}
web: <start-command>
```

**Notes:**

* Some languages auto-detect a start command (e.g., Go binaries, Spring Boot JARs)
* Other languages require a `Procfile` to start a web server

## Build Examples

```bash theme={null}
# Basic build with auto-detection
cpln image build --name my-app:v1 --push

# Use a different builder
cpln image build --name my-app:v1 --push -B gcr.io/buildpacks/builder:google-22

# Add a specific buildpack (e.g., for Rust)
cpln image build --name my-rust-app:v1 --push -b docker.io/paketocommunity/rust

# Pass build-time environment variables
cpln image build --name my-app:v1 --push -e NODE_ENV=production -e LOG_LEVEL=info

# Use an env file
cpln image build --name my-app:v1 --push --env-file .env.build

# Build for a different platform
cpln image build --name my-app:v1 --push --platform linux/arm64

# Trust builder and extra buildpacks (useful in CI/CD)
cpln image build --name my-app:v1 --push --trust-builder --trust-extra-buildpacks
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Container starts but crashes immediately">
    The buildpack built your image but doesn't know how to start it. Common causes:

    1. **Missing Procfile**: Create a `Procfile` in your project root:
       ```
       web: <your-start-command>
       ```

    2. **Missing start script (Node.js)**: Add a `start` script to `package.json`:
       ```json theme={null}
       "scripts": {
         "start": "node server.js"
       }
       ```

    3. **Wrong port**: Your app must listen on the `$PORT` environment variable, not a hardcoded port.
  </Accordion>

  <Accordion title="Language not detected">
    Buildpacks detect languages based on specific files. Ensure you have the required files for your language:

    | Language  | Required File(s)                                                                    |
    | --------- | ----------------------------------------------------------------------------------- |
    | Node.js   | `package.json` + `package-lock.json`                                                |
    | Python    | `requirements.txt`, `uv.lock`, or `poetry.lock`                                     |
    | Go        | `go.mod`                                                                            |
    | Java      | `pom.xml` or `build.gradle`                                                         |
    | Ruby      | `Gemfile` + `Gemfile.lock`                                                          |
    | PHP       | `composer.json` + `composer.lock`                                                   |
    | Rust      | `Cargo.toml` + `Cargo.lock` (requires `-b docker.io/paketocommunity/rust`)          |
    | C# / .NET | `.csproj`, `.fsproj`, or `.sln` (requires `-B paketobuildpacks/builder-jammy-base`) |

    <Note>
      Rust and C# / .NET are not supported by the default `heroku/builder:24`. You must specify an additional buildpack or use a different builder as shown above.
    </Note>
  </Accordion>

  <Accordion title="Build fails with 'untrusted builder'">
    In CI/CD environments, add the trust flags:

    ```bash theme={null}
    cpln image build --name my-app:v1 --push --trust-builder --trust-extra-buildpacks
    ```
  </Accordion>

  <Accordion title="Rust or .NET not building">
    These languages require different builders or buildpacks:

    **Rust:**

    ```bash theme={null}
    cpln image build --name my-app:v1 --push -b docker.io/paketocommunity/rust
    ```

    **C# / .NET:**

    ```bash theme={null}
    cpln image build --name my-app:v1 --push -B paketobuildpacks/builder-jammy-base
    ```
  </Accordion>

  <Accordion title="Build is slow">
    Buildpacks cache dependencies between builds. If builds are slow:

    1. Ensure you're not using `--no-cache` unless necessary
    2. Check if your dependency files changed (triggers full rebuild)
    3. Consider using a builder optimized for your language
  </Accordion>
</AccordionGroup>

## Learn More

<CardGroup cols={2}>
  <Card title="Images Reference" href="/reference/image" icon="book">
    Conceptual overview of images in Control Plane
  </Card>

  <Card title="Push Images Guide" href="/guides/push-image" icon="upload">
    Detailed guide for building and pushing images
  </Card>

  <Card title="CLI Image Commands" href="/cli-reference/commands/image" icon="terminal">
    Full CLI command reference
  </Card>

  <Card title="Buildpacks.io" href="https://buildpacks.io/docs/" icon="arrow-up-right-from-square">
    Official Cloud Native Buildpacks documentation
  </Card>
</CardGroup>
