> ## Documentation Index
> Fetch the complete documentation index at: https://controlplanecorporation-jakob-ess-2-0-0.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Images

> Build, push, pull, and manage container images with the Control Plane CLI.

The CLI provides powerful commands for working with container images. Build locally, push to your org's private registry, pull from external registries, and copy images between organizations.

## Quick Reference

| Command                   | Description                                                |
| ------------------------- | ---------------------------------------------------------- |
| `cpln image build`        | Build images locally or remotely, and optionally push them |
| `cpln image docker-login` | Authenticate Docker to your org's registry                 |
| `cpln image get`          | List or view images in your org                            |
| `cpln image copy`         | Copy images between organizations                          |
| `cpln image delete`       | Delete images from your registry                           |

## Build and Push Images

The most common workflow is building and pushing a local application:

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

This command:

1. Builds your image using the Dockerfile in the current directory
2. Tags it for your org's private registry
3. Pushes it to `your-org.registry.cpln.io/my-app:v1`

<Tip>
  No Docker on this machine or CI runner? Add `--remote` to build remotely — the image is built and pushed for you: `cpln image build --name my-app:v1 --remote`.
</Tip>

### Build Options

<Tabs>
  <Tab title="With Dockerfile">
    ```bash theme={null}
    # Build from current directory
    cpln image build --name my-app:v1 --push

    # Specify a Dockerfile
    cpln image build --name my-app:v1 --dockerfile ./docker/Dockerfile.prod --push

    # Build from a different directory
    cpln image build --name my-app:v1 --push --dir ./my-project

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

    # Build without cache
    cpln image build --name my-app:v1 --push --no-cache
    ```

    | Flag               | Description                                                  |
    | ------------------ | ------------------------------------------------------------ |
    | `--dockerfile`     | Path to Dockerfile (default: `./Dockerfile`)                 |
    | `--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                                    |
    | `--platform`, `-p` | Target platform (default: `linux/amd64`)                     |

    <Info>
      When `--dir` is specified, the Dockerfile in that directory is used by default. Use `--dockerfile` to override this behavior.
    </Info>
  </Tab>

  <Tab title="With Buildpacks">
    ```bash theme={null}
    cpln image build --name my-app:v1 --push
    ```

    **Buildpack options:**

    | Flag                       | Description                                                             |
    | -------------------------- | ----------------------------------------------------------------------- |
    | `--builder`, `-B`          | CNB-compatible builder image (default: `heroku/builder:24_linux-amd64`) |
    | `--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`)                                |

    **Examples:**

    ```bash theme={null}
    # 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
    ```

    **Common builders:**

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

    <Info>
      For language-specific requirements and conventions, see the [Buildpacks Guide](/guides/buildpacks).
    </Info>
  </Tab>

  <Tab title="Without Docker (remote)">
    Build remotely instead of through a local Docker daemon. The CLI uploads the build folder, Control Plane detects how to build it, and the image is pushed to your org's private registry, so `--push` is not used.

    ```bash theme={null}
    # Build the current folder
    cpln image build --name my-app:v1 --remote

    # Build a different folder
    cpln image build --name my-app:v1 --remote --dir ./my-project

    # Build a repository instead of a local folder
    cpln image build --name my-app:v1 --remote --repo https://github.com/my-org/my-app --branch main

    # Start the build and return immediately
    cpln image build --name my-app:v1 --remote --detach
    ```

    | Flag         | Description                                                                      |
    | ------------ | -------------------------------------------------------------------------------- |
    | `--remote`   | Build remotely and push the resulting image                                      |
    | `--dir`      | Folder to upload (default: current directory)                                    |
    | `--repo`     | HTTPS URL of a GitHub or GitLab repository to build instead of a folder          |
    | `--branch`   | Branch to build (requires `--repo`, defaults to the repository's default branch) |
    | `--detach`   | Return as soon as the build starts instead of following it                       |
    | `--no-cache` | Ignore cached layers and re-upload the whole folder                              |

    **What gets uploaded:** the folder is filtered by `.dockerignore`, or by `.gitignore` when there is no `.dockerignore`, and is limited to 500 MB and 20,000 files. Common junk such as `.git`, `node_modules`, `__pycache__`, and `.venv` is excluded either way. Later builds of the same image upload only the files that changed. Symlinks travel as links, so one pointing outside the build folder fails the build.

    <Info>
      A remote build detects how to build the source itself, so the local build flags do not apply. `--dockerfile`, `--builder`, `--buildpack`, `--env`, `--env-file`, `--trust-builder`, `--trust-extra-buildpacks`, `--platform`, and `--push` are rejected together with `--remote`, and the image is built for `linux/amd64`.
    </Info>

    Build logs stream until the image is pushed. Pressing `Ctrl+C` stops watching but leaves the build running remotely; check the result with `cpln image get my-app:v1`.

    <Note>
      Building a private repository requires the org's connection to GitHub or GitLab. The first build that needs it opens a browser to authorize the connection and then resumes on its own. In a non-interactive session, the CLI prints the connect URL and exits so you can authorize it and re-run the build.
    </Note>
  </Tab>
</Tabs>

## Use Images in Workloads

Reference your pushed images when creating workloads:

```bash theme={null}
cpln workload create --name my-app --gvc my-gvc \
  --image //image/my-app:v1 --port 8080 --public
```

### Image Reference Formats

| Format                           | Description                          |
| -------------------------------- | ------------------------------------ |
| `//image/IMAGE:TAG`              | Image in your org's registry         |
| `ORG.registry.cpln.io/IMAGE:TAG` | Image in another org's registry      |
| `nginx:latest`                   | Public image from Docker Hub         |
| `gcr.io/project/IMAGE:TAG`       | Image from Google Container Registry |

## Authenticate Docker

For direct Docker operations, authenticate to your org's registry:

```bash theme={null}
cpln image docker-login
```

Then use standard Docker commands:

```bash theme={null}
docker pull your-org.registry.cpln.io/my-app:v1
docker push your-org.registry.cpln.io/my-app:v1
```

## List and Manage Images

```bash theme={null}
# List all images in your org
cpln image get

# Get details for a specific image
cpln image get my-app:v1

# Delete an image
cpln image delete my-app:v1
```

## Copy Images Between Orgs

Copy an image to another organization:

```bash theme={null}
cpln image copy my-app:v1 --to-org destination-org
```

Copy with a different name:

```bash theme={null}
cpln image copy my-app:v1 --to-org destination-org --to-name renamed-app:v1
```

<Info>
  For cross-org copies with different credentials, use `--to-profile`. See the [Copy Images guide](/guides/copy-image).
</Info>

## CI/CD Authentication

For automated pipelines, set `CPLN_TOKEN` in your CI/CD platform's secrets (e.g., GitLab CI/CD variables, GitHub secrets) and use the CLI directly:

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

The CLI automatically uses `CPLN_TOKEN` when available.

On runners without a Docker daemon, swap `--push` for `--remote` and the image is built and pushed remotely instead:

```bash theme={null}
cpln image build --name my-app:$CI_COMMIT_SHA --remote
```

For direct Docker access, authenticate with a service account:

```bash theme={null}
echo $CPLN_TOKEN | docker login your-org.registry.cpln.io -u '<token>' --password-stdin
```

See [CI/CD Usage](/cli-reference/ci-cd-development/ci-cd) for complete automation setup.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Docker is not installed or the daemon is not running">
    Start Docker, or build without it:

    ```bash theme={null}
    cpln image build --name my-app:v1 --remote
    ```
  </Accordion>

  <Accordion title="The folder exceeds the 500 MB (or 20,000 entry) limit">
    A remote build uploads the whole build folder. Exclude what the build does not need by adding the large paths to `.dockerignore`, then re-run the build.
  </Accordion>

  <Accordion title="unknown shorthand flag: 'f' in -f">
    Docker Buildx is not installed. Install it:

    ```bash theme={null}
    curl -sSL "https://github.com/docker/buildx/releases/download/v0.29.1/buildx-v0.29.1.linux-amd64" \
      | install -m 0755 -D /dev/stdin ~/.docker/cli-plugins/docker-buildx
    ```
  </Accordion>

  <Accordion title="Authentication failed or 403">
    Re-run `cpln image docker-login` to refresh credentials and double check that you don't have typos in the org name.
  </Accordion>

  <Accordion title="Push denied">
    Verify you have push permission on images. Check your policies or refresh your service account token.
  </Accordion>

  <Accordion title="Image too large">
    Optimize your Dockerfile:

    * Use multi-stage builds
    * Start from smaller base images
    * Remove unnecessary files
  </Accordion>
</AccordionGroup>

## Learn More

<CardGroup cols={2}>
  <Card title="Buildpacks Guide" href="/guides/buildpacks" icon="cubes">
    Language-specific conventions for building without Dockerfiles
  </Card>

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

  <Card title="Pull Images" href="/guides/pull-image" icon="download">
    Configure workloads to pull from private registries
  </Card>

  <Card title="Image Command Reference" href="/cli-reference/commands/image" icon="book">
    Full command documentation
  </Card>
</CardGroup>
