Skip to main content
Install the Control Plane CLI inside container images to use it in CI jobs, Cron Workloads, or custom automation containers.

When to use this

Install cpln in a container image for:
  • CI/CD jobs - Run cpln commands in containerized pipelines
  • Cron Workloads - Execute automation tasks in Control Plane cron workloads
  • Custom automation images - Bundle cpln with your tools and scripts
Never bake credentials into container images. Pass tokens at runtime via environment variables or secret managers.

Installation methods

Use this method if your base image already includes Node.js (16 or later).
Dockerfile
FROM node:20-slim

# Pin the CLI version for reproducible builds
ARG CPLN_CLI_VERSION=3.7.5

# Install the Control Plane CLI
RUN npm install -g @controlplane/cli@${CPLN_CLI_VERSION} && \
    cpln --version

WORKDIR /app

# Keep container running for testing (remove in production)
CMD ["tail", "-f", "/dev/null"]
Build and run:
bash
# Build the image
docker build -t cpln-test .

# Run in a container
docker run -d --name cpln-test \
  -e CPLN_TOKEN="$CPLN_TOKEN" \
  -e CPLN_ORG="my-org" \
  -e CPLN_GVC="my-gvc" \
  cpln-test
Exec into the container:
bash
docker exec -it cpln-test bash
Test the CLI:
bash
# List all workloads
cpln workload get
Cleanup:
bash
docker stop cpln-test && docker rm cpln-test

Pin the CLI version

Always pin the CLI version for reproducible builds:
ARG CPLN_CLI_VERSION=3.7.5
RUN npm install -g @controlplane/cli@${CPLN_CLI_VERSION}
Check available versions:

Runtime authentication

Pass secrets via environment variables

Set at minimum CPLN_TOKEN when running the container:
docker run --rm \
  -e CPLN_TOKEN="$CPLN_TOKEN" \
  -e CPLN_ORG="my-org" \
  -e CPLN_GVC="my-gvc" \
  your-image:tag \
  cpln workload get
Never print CPLN_TOKEN in logs or commit it to version control.

Using cpln in automation

Once installed, execute CLI commands from your application code:
import { spawn } from "node:child_process";

const proc = spawn("cpln", ["workload", "get", "--gvc", "my-gvc"], {
  stdio: "inherit",
  env: process.env,
});

proc.on("exit", (code) => {
  process.exit(code ?? 1);
});

Common workflows

Build and push images

cpln image build --name <image-name>:<image-tag> --push

Apply resources

# Apply from a file
cpln apply --file resources.yaml

# Apply from stdin
cat resources.yaml | cpln apply --file -

Execute workload commands

cpln workload get --gvc my-gvc
cpln workload exec my-app --gvc my-gvc -- echo hello world

Troubleshooting

Verify the binary is in PATH and executable:
RUN cpln --version
Ensure the binary is copied to a directory in PATH (e.g., /usr/local/bin).
  1. Verify CPLN_TOKEN is set at runtime:
    docker run --rm -e CPLN_TOKEN="$CPLN_TOKEN" your-image cpln profile get
    
  2. Check the token isn’t truncated
Re-run Docker login in your container:
cpln image docker-login
Ensure the service account has access to the image registry.
For more troubleshooting help, see the Troubleshooting page.

Best practices

Keep final images small by using multi-stage builds to separate download/build tools from the runtime image.
Always specify an exact CLI version for reproducible builds:
ARG CPLN_CLI_VERSION=3.7.5
RUN npm install -g @controlplane/cli@${CPLN_CLI_VERSION}
Pass tokens at runtime via environment variables or secret managers. Never include them in the image.
Set CPLN_ORG and CPLN_GVC as environment variables so you don’t need to pass --org and --gvc flags with every command:
docker run --rm \
  -e CPLN_TOKEN="$CPLN_TOKEN" \
  -e CPLN_ORG="my-org" \
  -e CPLN_GVC="my-gvc" \
  your-image:tag
Add a verification step:
RUN cpln --version
This catches installation issues during the build.

Next steps