Skip to main content
πŸŽ“ Claude Code Masterclass Learn AI-assisted development on Udemy β€” plus the companion book on Leanpub & Amazon. Start Learning
Buildah vs Kaniko: Container Image Building Without Docker
DevOps

Buildah vs Kaniko: Container Image Building Without Docker

Buildah vs Kaniko for rootless, daemonless container image builds in CI/CD pipelines. Security, performance, Kubernetes integration, and GitLab/GitHub Actions examples.

LB
Luca Berton
Β· 1 min read

Why Not Just Docker Build?

Traditional docker build requires:

  • Docker daemon running (root privileges)
  • Docker socket access (security risk in CI)
  • Privileged containers in Kubernetes

Both Buildah and Kaniko solve this with daemonless, rootless builds.

Buildah

Buildah builds OCI container images without a daemon. Created by Red Hat, it integrates with Podman and CRI-O.

Basic Usage

# Build from Dockerfile
buildah bud -t myapp:latest .

# Scripted build (no Dockerfile needed)
container=$(buildah from registry.access.redhat.com/ubi9/ubi-minimal)
buildah run $container -- dnf install -y python3
buildah copy $container ./app /opt/app
buildah config --cmd "python3 /opt/app/main.py" $container
buildah commit $container myapp:latest
buildah push myapp:latest docker://registry.example.com/myapp:latest

In GitLab CI (Rootless)

build:
  image: quay.io/buildah/stable
  stage: build
  variables:
    STORAGE_DRIVER: vfs
    BUILDAH_FORMAT: docker
  script:
    - buildah login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - buildah bud --layers -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - buildah push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

In GitHub Actions

- name: Build with Buildah
  uses: redhat-actions/buildah-build@v2
  with:
    image: myapp
    tags: latest ${{ github.sha }}
    containerfiles: ./Dockerfile
    
- name: Push
  uses: redhat-actions/push-to-registry@v2
  with:
    image: myapp
    registry: ghcr.io/${{ github.repository_owner }}

Strengths

  • Rootless operation β€” no privilege escalation
  • Dockerfile compatible β€” drop-in replacement for docker build
  • Scripted builds β€” build without Dockerfile using shell commands
  • Layer caching β€” --layers flag enables layer reuse
  • OCI-native β€” produces standard OCI images
  • Multi-arch β€” buildah manifest for cross-platform images

Limitations

  • Linux only β€” no macOS/Windows support
  • CI environments β€” needs vfs storage driver in containers (slower)
  • Not in Kubernetes pods natively β€” needs privileged or user namespace

Kaniko

Kaniko builds container images inside Kubernetes without Docker daemon or root access. Created by Google.

In Kubernetes (Pod)

apiVersion: v1
kind: Pod
metadata:
  name: kaniko-build
spec:
  containers:
    - name: kaniko
      image: gcr.io/kaniko-project/executor:latest
      args:
        - "--dockerfile=Dockerfile"
        - "--context=git://github.com/org/repo.git#refs/heads/main"
        - "--destination=registry.example.com/myapp:latest"
        - "--cache=true"
        - "--cache-repo=registry.example.com/cache"
      volumeMounts:
        - name: docker-config
          mountPath: /kaniko/.docker/
  volumes:
    - name: docker-config
      secret:
        secretName: registry-credentials
  restartPolicy: Never

In GitHub Actions

- name: Build with Kaniko
  uses: aevea/action-kaniko@v0.12.0
  with:
    image: myapp
    tag: ${{ github.sha }}
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
    cache: true
    cache_registry: ghcr.io/${{ github.repository }}/cache

In GitLab CI

build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - |
      cat > /kaniko/.docker/config.json << EOF
      {"auths":{"$CI_REGISTRY":{"auth":"$(echo -n $CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD | base64)"}}}
      EOF
    - /kaniko/executor
        --context $CI_PROJECT_DIR
        --dockerfile $CI_PROJECT_DIR/Dockerfile
        --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
        --cache=true

Strengths

  • Runs in Kubernetes unprivileged β€” no root, no daemon, no socket
  • Remote context β€” pull from Git, S3, GCS directly
  • Layer caching β€” push cache layers to registry
  • Reproducible β€” consistent builds regardless of host
  • Multi-stage support β€” full Dockerfile support

Limitations

  • No interactive debugging β€” can’t exec into build
  • Slower first builds β€” no local layer cache
  • Limited RUN caching β€” only layer-level, not apt/pip cache
  • Snapshot overhead β€” filesystem snapshotting adds ~10-30% time
  • No scripted builds β€” Dockerfile only

Head-to-Head

FactorBuildahKaniko
Runs in K8s pods⚠️ Needs configβœ… Native
Dockerfile supportβœ… Fullβœ… Full
Scripted buildsβœ…βŒ
Build speedFaster (native)Slower (snapshots)
Layer cachingLocal + registryRegistry only
Multi-archβœ… buildah manifest❌
Security modelUser namespacesNo root needed
Maintained byRed HatGoogle

Build Time Comparison

Building a Node.js app (500MB image, 12 layers):

ScenarioBuildahKaniko
Cold build (no cache)45s62s
Warm build (cached layers)8s18s
Only app code changed12s22s

When to Choose

Choose Buildah when:

  • GitLab CI/GitHub Actions (not in K8s)
  • You need scripted builds (no Dockerfile)
  • Multi-architecture images
  • Fastest possible build times
  • Red Hat / Podman ecosystem

Choose Kaniko when:

  • Building inside Kubernetes (Tekton, Argo Workflows)
  • Zero privilege escalation requirement
  • Remote build contexts (Git, S3)
  • Shared CI clusters where Docker socket is unavailable
  • Google Cloud Build or GKE environments

Use Both:

  • Kaniko for production CI in Kubernetes
  • Buildah for local development and testing

Free 30-min AI & Cloud consultation

Book Now