Dockerfile Support¶
When a Dockerfile is present at the repository root, the PaaS build planner
automatically routes your build through the dedicated paas-dockerfile-pipeline
instead of the Paketo buildpack pipeline.
Detection flow¶
sequenceDiagram
participant D as Developer
participant CP as Control Plane
participant LD as language_detector
participant TK as Tekton (paas-build)
participant K as Kaniko
participant H as Harbor
participant T as Trivy
D->>CP: POST /v1/apps/{id}/builds
CP->>LD: detect_language(repo)
LD-->>CP: DetectedBuildpack::Dockerfile (priority 1)
CP->>TK: PipelineRun (paas-dockerfile-pipeline)
TK->>TK: clone (git-clone Task)
TK->>K: kaniko-build (Dockerfile context)
K->>H: push image
TK->>T: trivy-scan --severity CRITICAL --exit-code 1
T-->>TK: pass / fail
TK-->>CP: image URL or build error
Dockerfile always wins over buildpack indicator files (package.json,
go.mod, Cargo.toml, etc.) — you don't need a paas.toml override to
opt out of buildpacks.
When to use a Dockerfile¶
- Official images that already ship one: n8n, vLLM, Metabase, Plausible, Mattermost, …
- Stacks not covered by the eight Paketo buildpacks (see Buildpacks Detection)
- Custom base image or specific OS packages
- Optimised multi-stage builds (compile-time deps in stage 1, runtime image in stage 2)
Multi-stage builds¶
Kaniko supports multi-stage Dockerfiles natively — no extra config:
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
Build args¶
Pass build-time variables via paas.toml:
The control plane forwards these as --build-arg KEY=VAL flags to Kaniko.
Empty values are allowed; values containing spaces are not (current
build-args-str parameter is space-separated). Use a comma-separated env
file or escape your value if you need spaces.
Security¶
- Trivy scan runs after every build with
--severity CRITICAL --exit-code 1. Builds with at least one CRITICAL CVE fail before the image is taggedlatestin Harbor — the pipeline never marks the build successful. - Image size warnings >1GB and refusal >5GB: Phase 2.
USER rootwarning at build-time: Phase 2.
Troubleshooting¶
apt-get404: combineapt-get update && apt-get install -y …in a singleRUNso the metadata cache is fresh in the same layer.FROM scratch: the binary must be statically linked — no glibc, no dynamic loader. Use musl for Rust/Go.- Multi-stage failure: stage names (after
AS …) must be unique within a single Dockerfile. - Trivy fails with CRITICAL: check the exact CVE id in the build log, upgrade the affected package or pin a base image with the fix.
Security warnings¶
USER root warning¶
Trivy scans each built image for security configuration issues. When the
final stage of a Dockerfile runs as root (i.e. no USER directive,
or USER root explicitly), Trivy emits a MEDIUM-severity finding in the
post-build scan.
Recommendation — end every Dockerfile with a non-root user:
A future Phase 2 update will surface USER-root warnings directly in the PaaS dashboard before the image is pushed, so tenants receive actionable feedback earlier in the build loop instead of having to read the Trivy log after the fact.
Image size limits¶
Phase 2 — a post-kaniko Tekton step will inspect the pushed image
manifest (via skopeo inspect --raw or crane manifest) and apply the
following policies:
| Image size | Action |
|---|---|
| < 1 GB | None |
| 1 GB – 5 GB | Warning visible in dashboard |
| > 5 GB | Build refused (exit 1) — cluster limit |
Currently kaniko builds without any size constraint. To keep your images small until Phase 2 ships, the established practices are:
- Use multi-stage builds (heavy compile-time deps in stage 1, only the runtime artifacts copied into stage 2)
- Choose minimal base images:
alpine,distroless,scratch - Avoid
apt-getin the final stage; install only the runtime deps - Run
docker historyon a built image locally to spot the layers that bloat your final size
Related¶
- Buildpacks Detection (Paketo alternative)
- Git Push Deploy
- Apps