Tekton is an open-source CI/CD system running on k8s.
The CNB project has created a reference “task” for performing buildpacks builds with or without extensions (aka Dockerfile to be applied) top
of the lifecycle tool (i.e. they do not use pack
).
The Buildpacks Phases Task calls the individual lifecycle binaries (prepare, analyze, detect, restore, build or extender, export), to run each phase in a separate container.
The uid and gid as defined part of the builder image will be used to build the image.
The different parameters to customize the task are defined part of the task’s documentation under the section parameters
.
NOTE: Prior to installing
Tekton
, we recommend reviewing the basic Tekton concepts in the documentation.
Before we get started, make sure you’ve got the following installed:
Install kubectlTo start, set up a Tekton
version >= 1.0
, using the Tekton documentation.
We also recommend using the Tekton dashboard
. To install it, follow the steps in the dashboard docs, and
start the dashboard server.
NOTE: If you run Tekton on a Kind or Minikube Kubernetes cluster, be sure to set the
coschedule
flag todisabled
within thefeature-flags
ConfigMap.
Install the latest version of the buildpacks task (currently 0.3
), by running:
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/refs/heads/main/task/buildpacks-phases/0.3/buildpacks-phases.yaml
In order to set up our pipeline, we will need to define a few things:
Pipeline
defines a series of Tasks
that accomplish a specific build or delivery goal. The Pipeline
can be triggered by an event or invoked from a PipelineRun
.PipelineResource
defines locations for inputs ingested and outputs produced by the steps in Tasks
.PersistentVolumeClaim
(a general Kubernetes concept, generally shortened to PVC) is
a request for storage by a user.Create a file resources.yml
that defines a PersistentVolumeClaim
able to store the git cloned project and buildpacks files:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: buildpacks-source-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
NOTE: You don’t need to use authorization if you are pushing to a local registry. However, if you are pushing to a remote registry (e.g.
DockerHub
,GCR
, `quay.io), you need to add authorization
Create a Secret
containing username and password that the build should use to authenticate to the container registry.
kubectl create secret docker-registry registry-user-pass \
--docker-username=<USERNAME> \
--docker-password=<PASSWORD> \
--docker-server=<LINK TO REGISTRY, e.g. https://index.docker.io/v1/ > \
--namespace default
Create a file sa.yml
that defines a ServiceAccount
that uses the newly created secret:
apiVersion: v1
kind: ServiceAccount
metadata:
name: buildpacks-service-account
secrets:
- name: registry-user-pass
NOTE: This service account will be used by Tekton in order to mount the credentials as docker config file part of the pod running buildpacks
Create a file pipeline.yml
that defines the Pipeline
, and relevant resources:
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: buildpacks-test-pipeline
spec:
params:
- name: git-url
type: string
description: URL of the project to git clone
- name: source-subpath
type: string
description: The subpath within the git project
- name: image
type: string
description: image URL to push
- name: builder
type: string
description: builder image URL
- name: env-vars
type: array
description: env vars to pass to the lifecycle binaries
workspaces:
- name: source-workspace # Directory where application source is located. (REQUIRED)
tasks:
- name: fetch-repository # This task fetches a repository from github, using the `git-clone` task you installed
taskRef:
resolver: http
params:
- name: url
value: https://raw.githubusercontent.com/tektoncd/catalog/refs/heads/main/task/git-clone/0.9/git-clone.yaml
workspaces:
- name: output
workspace: source-workspace
params:
- name: url
value: "$(params.git-url)"
- name: deleteExisting
value: "true"
- name: buildpacks # This task uses the `buildpacks phases` task to build the application
taskRef:
name: buildpacks-phases
runAfter:
- fetch-repository
workspaces:
- name: source
workspace: source-workspace
params:
- name: APP_IMAGE
value: "$(params.image)"
- name: SOURCE_SUBPATH
value: "$(params.source-subpath)"
- name: CNB_BUILDER_IMAGE
value: "$(params.builder)"
- name: CNB_ENV_VARS
value: "$(params.env-vars[*])"
- name: display-results
runAfter:
- buildpacks
taskSpec:
steps:
- name: print
image: docker.io/library/bash:5.1.4@sha256:b208215a4655538be652b2769d82e576bc4d0a2bb132144c060efc5be8c3f5d6
script: |
#!/usr/bin/env bash
set -e
echo "Digest of created app image: $(params.DIGEST)"
params:
- name: DIGEST
params:
- name: DIGEST
value: $(tasks.buildpacks.results.APP_IMAGE_DIGEST)
Apply these configurations, using kubectl
:
kubectl apply -f resources.yml -f sa.yml -f pipeline.yml
Create a file run.yml
, which defines the PipelineRun
:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: buildpacks-test-pipeline-run
spec:
taskRunTemplate:
serviceAccountName: buildpacks-service-account # Only needed if you set up authorization
pipelineRef:
name: buildpacks-test-pipeline
workspaces:
- name: source-workspace
subPath: source
persistentVolumeClaim:
claimName: buildpacks-source-pvc
params:
- # The url of the git project to clone (REQURED).
name: git-url
value: https://github.com/buildpacks/samples
- # This is the path within the git project you want to build (OPTIONAL, default: "")
name: source-subpath
value: "apps/java-maven"
- # This is the builder image we want the task to use (REQUIRED).
name: builder
value: cnbs/sample-builder:noble
- name: image
value: <REGISTRY/IMAGE NAME, eg gcr.io/test/image > # This defines the name of output image
Make sure to replace
<REGISTRY/IMAGE NAME>
with your image path.
Apply it with:
kubectl apply -f run.yml
Look at the PipelineRun
logs by running
kubectl describe pipelinerun buildpacks-test-pipeline-run
or by using the Tekton Dashboard.
Once the application is successfully built, you can pull and run it by running:
docker | podman pull <REGISTRY/IMAGE NAME>
docker | podman run -it <REGISTRY/IMAGE NAME>
If your builder image supports the extension mechanism able to customize the build or the run (aka execution), then you can replay this scenario by simply changing within the PipelineRun
resource file the builder parameter
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: buildpacks-test-pipeline-run
spec:
taskRunTemplate:
serviceAccountName: buildpacks-service-account
pipelineRef:
name: buildpacks-test-pipeline
workspaces:
- name: source-workspace
subPath: source
persistentVolumeClaim:
claimName: buildpacks-source-pvc
params:
- name: image
value: <REGISTRY/IMAGE NAME, eg gcr.io/test/image>
- name: git-url
value: https://github.com/quarkusio/quarkus-quickstarts
- name: source-subpath
value: "getting-started"
- name: builder
value: paketobuildpacks/builder-ubi8-base:0.1.30
- name: env-vars
value:
- BP_JVM_VERSION=21
When the build process starts, then you should see, part of the extender step, if you build a Java runtime (Quarkus, Spring boot, etc) such log messages if the extension installs by example a different JDK
2025-06-27T11:32:25.067007701Z time="2025-06-27T11:32:25Z" level=info msg="Performing slow lookup of group ids for root"
2025-06-27T11:32:25.067243910Z time="2025-06-27T11:32:25Z" level=info msg="Running: [/bin/sh -c echo ${build_id}]"
2025-06-27T11:32:25.095150183Z 9e447871-e415-4018-a860-d5a66d925a57
2025-06-27T11:32:25.096877516Z time="2025-06-27T11:32:25Z" level=info msg="Taking snapshot of full filesystem..."
2025-06-27T11:32:25.280396774Z time="2025-06-27T11:32:25Z" level=info msg="Pushing layer oci:/kaniko/cache/layers/cached:a035cdb3949daa8f4e7b2c523ea0d73741c7c2d5b09981c261ebae99fd2f3233 to cache now"
2025-06-27T11:32:25.280572023Z time="2025-06-27T11:32:25Z" level=info msg="RUN microdnf --setopt=install_weak_deps=0 --setopt=tsflags=nodocs install -y openssl-devel java-21-openjdk-devel nss_wrapper which && microdnf clean all"
2025-06-27T11:32:25.280577315Z time="2025-06-27T11:32:25Z" level=info msg="Cmd: /bin/sh"
2025-06-27T11:32:25.280578398Z time="2025-06-27T11:32:25Z" level=info msg="Args: [-c microdnf --setopt=install_weak_deps=0 --setopt=tsflags=nodocs install -y openssl-devel java-21-openjdk-devel nss_wrapper which && microdnf clean all]"
...
To clean up, run:
kubectl delete -n default pipelinerun buildpacks-test-pipeline-run
kubectl delete -n default pipeline buildpacks-test-pipeline
kubectl delete -n default buildpacks-phases
kubectl delete -n default pvc buildpacks-source-pvc
The Buildpacks task can be accessed at:
Some general resources for Tekton are: