How do you build and push container images using Tekton (Kaniko, Buildah)?
Quick Answer
Tekton builds and pushes container images using unprivileged builder tools like Kaniko or Buildah that run as regular containers within Task steps, reading Dockerfiles from a workspace and pushing the resulting image to a registry using credentials provided through Kubernetes Secrets.
Detailed Answer
Think of building container images in Tekton like assembling a product in a clean-room factory. Traditional Docker builds require access to the Docker daemon, which is like needing the factory's master control panel to assemble a single product. Kaniko and Buildah are self-contained assembly stations that can build the product independently without needing the master control panel, making them safe to operate in shared environments where giving every worker access to the master controls would be a security risk.
Kaniko is the most popular image builder in Tekton pipelines because it runs entirely in userspace without requiring a Docker daemon or privileged container mode. The Kaniko executor reads a Dockerfile from the workspace, executes each instruction in a sandboxed environment, and pushes the resulting image layers directly to a container registry. In a Tekton Task, you create a step using the gcr.io/kaniko-project/executor image, pass the Dockerfile location and build context via arguments, and specify the destination registry and tag with the --destination flag. Kaniko supports multi-stage builds, build arguments, layer caching through a remote cache repository, and digest file output that integrates perfectly with Tekton Results. For the payments-api service, Kaniko reads the Dockerfile from the cloned source workspace, builds the Go binary in a builder stage, copies it into a distroless runtime image, and pushes the result to registry.acme.io/payments-api with both a git-sha tag and a semver tag.
Buildah offers an alternative approach that provides more flexibility and closer compatibility with Docker build behavior. Buildah supports Dockerfile-based builds through the buildah bud command, but also supports building images programmatically using buildah from, buildah copy, buildah run, and buildah commit commands. This programmatic approach is valuable when you need to construct images based on dynamic conditions that are difficult to express in a Dockerfile. Buildah can run without root privileges using the --storage-driver=vfs flag, though it typically needs some elevated capabilities. In Tekton, Buildah steps use the quay.io/buildah/buildah image and mount the container storage as an emptyDir volume. For the user-auth-service, a Buildah-based Task can conditionally include debug tools in development builds while producing minimal images for production, all within the same Task definition using script logic.
Registry authentication for both Kaniko and Buildah is handled through Kubernetes Secrets. Kaniko reads Docker credentials from a config.json file, which you provide either through Tekton's automatic credential injection via annotated Secrets on the service account, or by explicitly mounting a dockerconfigjson Secret to /kaniko/.docker/config.json. Buildah uses the --authfile flag pointing to a mounted credentials file. For multi-registry workflows where the checkout-service pipeline pulls base images from Docker Hub, caches layers in a GCR cache repository, and pushes the final image to a private ECR registry, you create separate Secrets for each registry and mount them into the builder step. Kaniko supports multiple --destination flags to push the same image to multiple registries in a single build, which is useful for disaster recovery setups where images must exist in two geographically separated registries.
Performance optimization is critical for production Tekton image builds. Kaniko's --cache=true flag enables layer caching using a remote registry as the cache backend, dramatically reducing build times for images where early layers like dependency installation rarely change. The --cache-repo flag specifies where cached layers are stored. For the order-processing-service with a large node_modules layer, enabling caching reduces build times from eight minutes to under two minutes when only application code changes. Buildah benefits from mounting a persistent cache volume for the package manager cache directory. Both tools support --snapshot-mode=redo in Kaniko and equivalent optimizations in Buildah to skip unchanged layers more efficiently. Always output the image digest to /tekton/results so downstream Tasks can reference the exact immutable image rather than a mutable tag that could be overwritten by a concurrent build.