Skip to content
Canopy is in pre-release. These docs describe the product at its public launch — commands, tool names, and integration examples reflect what you'll see once binaries ship. Join the waitlist →

Use Canopy in Docker

Canopy detects Docker containers at startup using two signals — the /.dockerenv sentinel file and /proc/1/cgroup runtime keywords — and automatically activates in ephemeral mode. No seat is reserved; the activation disappears when the container stops.

Pass the license key as an environment variable. Never bake it into an image.

Terminal window
docker run --rm \
-e CANOPY_LICENSE_KEY="$CANOPY_LICENSE_KEY" \
-e CANOPY_DOWNLOAD_URL="$CANOPY_DOWNLOAD_URL" \
-v "$(pwd):/repo" \
ubuntu:24.04 \
bash -c "
apt-get update && apt-get install -y curl ca-certificates
curl -fsSL \"\$CANOPY_DOWNLOAD_URL/canopy-linux-\$(uname -m)\" -o /usr/local/bin/canopy
chmod +x /usr/local/bin/canopy
canopy activate \"\$CANOPY_LICENSE_KEY\"
canopy health --repo /repo
"
FROM ubuntu:24.04
# Install Canopy binary into the image. Pass CANOPY_DOWNLOAD_URL as a
# build arg so the URL isn't hardcoded; pin canopy-linux-x86_64 (or
# canopy-linux-aarch64 for ARM images) since the build is single-arch.
ARG CANOPY_DOWNLOAD_URL
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
&& curl -fsSL "$CANOPY_DOWNLOAD_URL/canopy-linux-x86_64" -o /usr/local/bin/canopy \
&& chmod +x /usr/local/bin/canopy \
&& rm -rf /var/lib/apt/lists/*
# Activation is done at container runtime, not build time.
# Pass CANOPY_LICENSE_KEY via docker run -e or docker-compose environment.
ENTRYPOINT ["sh", "-c", "canopy activate \"$CANOPY_LICENSE_KEY\" && canopy serve /repo"]
Terminal window
docker run -e CANOPY_LICENSE_KEY="..." -v $(pwd):/repo my-canopy-image

Use Canopy in the build stage to check code quality, then discard the license from the final image:

# Stage 1: lint + health check
FROM ubuntu:24.04 AS canopy-check
ARG CANOPY_DOWNLOAD_URL
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
&& curl -fsSL "$CANOPY_DOWNLOAD_URL/canopy-linux-x86_64" -o /usr/local/bin/canopy \
&& chmod +x /usr/local/bin/canopy \
&& rm -rf /var/lib/apt/lists/*
COPY . /repo
ARG CANOPY_LICENSE_KEY
RUN canopy activate "$CANOPY_LICENSE_KEY" && \
canopy index /repo && \
canopy health --repo /repo
# Stage 2: production image — Canopy is not included, no license exposure
FROM node:22-slim AS production
COPY --from=canopy-check /repo/dist /app
CMD ["node", "/app/index.js"]
Terminal window
docker build \
--build-arg CANOPY_LICENSE_KEY="$CANOPY_LICENSE_KEY" \
--target production \
-t my-app:latest .

The CANOPY_LICENSE_KEY build arg is used only in the canopy-check stage and is not present in the final image.

docker-compose.yml
services:
canopy:
image: ubuntu:24.04
environment:
# Set CANOPY_LICENSE_KEY and CANOPY_DOWNLOAD_URL in a .env file
# (not checked into git).
CANOPY_LICENSE_KEY: ${CANOPY_LICENSE_KEY}
CANOPY_DOWNLOAD_URL: ${CANOPY_DOWNLOAD_URL}
volumes:
- .:/repo
command: >
bash -c "
apt-get update && apt-get install -y curl ca-certificates &&
curl -fsSL \"$$CANOPY_DOWNLOAD_URL/canopy-linux-$(uname -m)\" -o /usr/local/bin/canopy &&
chmod +x /usr/local/bin/canopy &&
canopy activate \"$$CANOPY_LICENSE_KEY\" &&
canopy serve /repo
"
Terminal window
# .env (add to .gitignore)
CANOPY_LICENSE_KEY=your-key-here
apiVersion: v1
kind: Secret
metadata:
name: canopy-license
type: Opaque
stringData:
key: "your-canopy-license-key"
---
apiVersion: batch/v1
kind: Job
metadata:
name: canopy-health-check
spec:
template:
spec:
containers:
- name: canopy
image: ubuntu:24.04
env:
- name: CANOPY_LICENSE_KEY
valueFrom:
secretKeyRef:
name: canopy-license
key: key
- name: CANOPY_DOWNLOAD_URL
value: "https://downloads.canopy.ironpinelabs.com/releases/latest"
command:
- bash
- -c
- |
apt-get update && apt-get install -y curl ca-certificates
curl -fsSL "$CANOPY_DOWNLOAD_URL/canopy-linux-$(uname -m)" -o /usr/local/bin/canopy
chmod +x /usr/local/bin/canopy
canopy activate "$CANOPY_LICENSE_KEY"
canopy health --repo /repo
volumeMounts:
- mountPath: /repo
name: source
volumes:
- name: source
persistentVolumeClaim:
claimName: source-pvc
restartPolicy: Never

Canopy detects Kubernetes via kubepods in /proc/1/cgroup and activates in ephemeral mode automatically.

VariableEffect
CANOPY_EPHEMERAL=1Force ephemeral mode (useful on VMs that look like containers)
CANOPY_EPHEMERAL=0Force persistent mode — seat IS consumed (useful for long-lived container agents)

WSL2 note: Some WSL2 configurations expose Docker cgroup entries even on the host. If Canopy incorrectly detects ephemeral mode on your WSL2 machine, set CANOPY_EPHEMERAL=0 in your shell profile.