Aller au contenu
Conteneurs & Orchestration medium

Kaniko - Build d'images conteneurs sans Docker daemon

36 min de lecture

Kaniko est un outil de build d’images OCI (Docker) qui fonctionne entièrement en userspace, sans daemon Docker. Conçu par Google puis repris par la communauté open source, il résout les problèmes de sécurité liés au Docker-in-Docker (DinD) en permettant de construire des images directement dans des conteneurs standard, sans privilèges root. C’est la solution de référence pour les builds dans Kubernetes Pods et les pipelines CI/CD sécurisés (GitLab CI, GitHub Actions, Tekton).

Cas d’usage principal : Vous avez besoin de construire des images dans Kubernetes ou GitLab CI, mais vous ne pouvez pas (ou ne voulez pas) exposer le socket Docker ou utiliser le mode privileged. Kaniko s’exécute comme un simple conteneur, lit votre Dockerfile, build les layers OCI, et push directement vers un registry — tout cela sans daemon.

Workflow Kaniko

Docker build classique nécessite un daemon Docker qui s’exécute avec des privilèges root et expose un socket Unix (/var/run/docker.sock). Dans Kubernetes ou en CI/CD, cette architecture pose des problèmes critiques de sécurité et de complexité.

Kaniko vs Docker Build

CritèreDocker buildKaniko
Daemon requis✅ Oui (dockerd)❌ Non (userspace pur)
Privilèges root✅ Requis❌ Utilisateur standard
Socket Docker/var/run/docker.sock❌ Aucun socket
Kubernetes❌ DinD complexe (privileged)✅ Pod standard non-root
Sécurité⚠️ Risque escalade privilèges✅ Isolation complète
CI/CD⚠️ Docker-in-Docker (nested)✅ Conteneur simple
Performance🚀 Très rapide (cache daemon)🏃 Rapide (cache registry)
Compatibilité Dockerfile✅ 100%✅ ~95% (limitations mineures)

Kaniko excelle dans les environnements où la sécurité et l’absence de daemon sont critiques, tandis que Docker build reste pertinent pour le développement local avec infrastructure Docker existante.

SituationOutil recommandéRaison
Build dans Kubernetes PodKanikoPas de daemon, pas de privileged
Pipeline GitLab CI / GitHub ActionsKanikoConteneur simple, sécurisé
Build Tekton / Argo WorkflowsKanikoNatif Kubernetes
Développement local (Docker installé)Docker buildPlus rapide, cache local
Multi-platform builds complexesDocker buildxSupport ARM64 + cache avancé
Environnement sans Docker disponibleKanikoFonctionne partout (userspace)

Kaniko ne s’installe pas comme un outil CLI classique : il s’exécute toujours en tant que conteneur. Vous lancez l’image gcr.io/kaniko-project/executor:v1.26.4, montez votre code source et Dockerfile, et Kaniko build + push l’image.

  1. Créer un Dockerfile de test

    Fenêtre de terminal
    mkdir -p /tmp/kaniko-test && cd /tmp/kaniko-test
    cat <<'EOF' > Dockerfile
    FROM alpine:3.21
    RUN apk add --no-cache curl
    CMD ["/bin/sh"]
    EOF
  2. Lancer Kaniko executor en conteneur

    Cette commande monte le répertoire courant dans le conteneur, build l’image, mais ne la push pas (--no-push).

    Fenêtre de terminal
    docker run --rm \
    -v "$PWD":/workspace \
    martizih/kaniko:v1.26.4 \
    --context=/workspace \
    --dockerfile=/workspace/Dockerfile \
    --destination=test-kaniko:1.0.0 \
    --no-push

    Comprendre les options de la commande : Kaniko executor accepte plusieurs paramètres critiques qui déterminent où trouver le code source, quel Dockerfile utiliser, et où pousser l’image finale. Voici les options essentielles à maîtriser :

    • --context : Répertoire contenant le Dockerfile et le build context
    • --dockerfile : Chemin vers le Dockerfile (si différent de Dockerfile)
    • --destination : Tag de l’image finale (format registry/image:tag)
    • --no-push : Empêche le push vers le registry (utile pour tester)
  3. Vérifier le build réussi

    Kaniko affiche les logs de build (layers, étapes FROM/RUN/CMD). Sortie attendue :

    INFO[0002] Retrieving image manifest alpine:3.21
    INFO[0002] Retrieving image alpine:3.21 from registry index.docker.io
    INFO[0003] Built cross stage deps: map[]
    INFO[0003] Retrieving image manifest alpine:3.21
    INFO[0003] FROM alpine:3.21
    INFO[0003] Unpacking rootfs as cmd RUN apk add --no-cache curl requires it.
    INFO[0003] RUN apk add --no-cache curl
    INFO[0003] Taking snapshot of full filesystem...
    INFO[0003] CMD ["/bin/sh"]
    INFO[0003] Skipping push to container registry due to --no-push flag

    L’image est construite mais non persistée (car Kaniko s’exécute dans un conteneur isolé). Contrairement à Docker build qui stocke l’image dans le daemon local, Kaniko build l’image en mémoire puis la détruit. Pour la récupérer et l’utiliser, vous avez deux options principales :

    • Push vers un registry : --destination ghcr.io/user/test-kaniko:1.0.0 (sans --no-push) — l’image devient accessible à tous vos environnements
    • Export en tar local : --tarPath /output/image.tar (voir section Gestion des images) — utile pour charger l’image avec docker load

Si vous utilisez Podman au lieu de Docker :

Fenêtre de terminal
podman run --rm \
-v "$PWD":/workspace:Z \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--dockerfile=/workspace/Dockerfile \
--destination=test-kaniko:1.0.0 \
--no-push

L’option :Z applique le contexte SELinux correct pour le volume monté.

Pour pousser des images vers un registry privé (GHCR, Harbor, GCR, ECR), Kaniko a besoin d’accéder au fichier de credentials Docker standard (~/.docker/config.json).

  1. Créer un Personal Access Token GitHub

    Allez dans Settings → Developer settings → Personal access tokens → Generate new token (classic).

    Permissions nécessaires : Pour que Kaniko puisse pousser des images vers GitHub Container Registry (GHCR), votre token GitHub doit avoir les scopes suivants :

    • write:packages : Permet de pousser de nouvelles images
    • read:packages : Permet de lire/télécharger des images existantes
    • delete:packages : Permet de supprimer des versions d’images (optionnel, mais recommandé pour le nettoyage)
  2. Login Docker pour générer config.json

    Fenêtre de terminal
    echo "$GITHUB_TOKEN" | docker login ghcr.io -u USERNAME --password-stdin

    Cela crée/met à jour ~/.docker/config.json avec les credentials encodés.

  3. Monter config.json dans Kaniko

    Fenêtre de terminal
    docker run --rm \
    -v "$PWD":/workspace \
    -v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
    martizih/kaniko:v1.26.4 \
    --context=/workspace \
    --dockerfile=/workspace/Dockerfile \
    --destination=ghcr.io/USERNAME/test-kaniko:1.0.0

    L’image est buildée et poussée automatiquement vers GHCR.

Alternative au fichier config.json : passer directement les credentials via variables d’environnement.

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-e REGISTRY_USERNAME=myuser \
-e REGISTRY_PASSWORD=mytoken \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/myuser/test-kaniko:1.0.0

Kaniko est conçu pour les pipelines CI/CD modernes. Voici des exemples production-ready pour GitLab CI, GitHub Actions et Tekton.

Créez .gitlab-ci.yml à la racine de votre projet :

stages:
- build
build-image:
stage: build
image:
name: martizih/kaniko:v1.26.4-debug
entrypoint: [""]
before_script:
# Créer config.json pour authentification registry
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
--cache=true
--cache-repo="${CI_REGISTRY_IMAGE}/cache"
only:
- main
- tags

Comprendre la configuration GitLab CI : Cette configuration exploite les variables CI/CD intégrées de GitLab pour authentifier automatiquement Kaniko auprès du Container Registry. Voici les éléments critiques à comprendre :

  • image.entrypoint: [""] : Nécessaire pour permettre à GitLab CI d’exécuter des commandes custom (sinon Kaniko démarre automatiquement)
  • Variables CI/CD intégrées : $CI_REGISTRY, $CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD — GitLab les fournit automatiquement, pas besoin de les configurer
  • --cache=true + --cache-repo : Active le cache pour accélérer les builds suivants (jusqu’à 70% de gain de temps)
  • Tag avec commit SHA : ${CI_COMMIT_SHORT_SHA} garantit l’unicité et la traçabilité de chaque image

Vérifier le build : Allez dans Build → Container Registry, votre image doit apparaître.

Créez .github/workflows/build.yml :

name: Build and Push Image
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4.2.2
- name: Login to GHCR
uses: docker/login-action@v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5.5.1
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
- name: Build and push with Kaniko
uses: int128/kaniko-action@v1.47.0
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache: true
cache-repository: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/cache
kaniko-args: |
--snapshot-mode=redo
--use-new-run

Comprendre le workflow GitHub Actions : Cette configuration utilise des actions communautaires pour simplifier le build et automatiser le tagging des images. GitHub fournit automatiquement un token d’authentification temporaire, ce qui évite de gérer manuellement les secrets. Voici les composants principaux :

  • Action int128/kaniko-action : Wrapper qui simplifie l’utilisation de Kaniko (gère le montage des volumes, la config Docker, etc.)
  • docker/metadata-action : Génère automatiquement les tags selon les conventions (semver pour les releases, SHA pour les commits, branch name pour les PR)
  • secrets.GITHUB_TOKEN : Token automatique avec permissions packages: write — GitHub le fournit à chaque workflow, durée de vie 1h
  • --snapshot-mode=redo : Améliore la performance du cache en comparant uniquement les fichiers modifiés (vs full qui scanne tout)
  • --use-new-run : Utilise l’exécution optimisée des commandes RUN (meilleure gestion des permissions et performance)

Alternative sans action (exécution directe) :

- name: Build with Kaniko executor
run: |
docker run --rm \
-v "${{ github.workspace }}":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--dockerfile=/workspace/Dockerfile \
--destination=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
--cache=true \
--cache-repo=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/cache

Tekton est un framework CI/CD natif Kubernetes. Voici une Task Tekton pour builder avec Kaniko :

apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko-build
spec:
params:
- name: IMAGE
description: Name (reference) of the image to build
- name: DOCKERFILE
description: Path to the Dockerfile to build
default: ./Dockerfile
- name: CONTEXT
description: The build context used by Kaniko
default: ./
workspaces:
- name: source
description: Holds the code to build
- name: dockerconfig
description: Docker config.json for registry auth
steps:
- name: build-and-push
image: martizih/kaniko:v1.26.4
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker
command:
- /kaniko/executor
args:
- --dockerfile=$(params.DOCKERFILE)
- --context=$(workspaces.source.path)/$(params.CONTEXT)
- --destination=$(params.IMAGE)
- --cache=true
- --cache-repo=$(params.IMAGE)/cache
- --snapshot-mode=redo
volumeMounts:
- name: $(workspaces.dockerconfig.volume)
mountPath: /kaniko/.docker

Utilisation dans un Pipeline :

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: build-app
spec:
params:
- name: image-name
type: string
default: ghcr.io/myorg/myapp
workspaces:
- name: shared-workspace
- name: docker-credentials
tasks:
- name: fetch-repository
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: https://github.com/myorg/myapp.git
- name: build-image
taskRef:
name: kaniko-build
runAfter:
- fetch-repository
workspaces:
- name: source
workspace: shared-workspace
- name: dockerconfig
workspace: docker-credentials
params:
- name: IMAGE
value: $(params.image-name):$(tasks.fetch-repository.results.commit)

Créer le Secret Kubernetes pour l’authentification :

Fenêtre de terminal
kubectl create secret docker-registry regcred \
--docker-server=ghcr.io \
--docker-username=USERNAME \
--docker-password=TOKEN \
--namespace=tekton-pipelines

Kaniko brille dans Kubernetes car il ne nécessite aucun privilège spécial, contrairement au Docker-in-Docker qui demande privileged: true ou le montage du socket Docker.

Kaniko dans Kubernetes

Créez un Pod qui build et push une image :

apiVersion: v1
kind: Pod
metadata:
name: kaniko-builder
namespace: ci-cd
spec:
restartPolicy: Never
initContainers:
# Clone du code source depuis Git
- name: git-clone
image: alpine/git:2.45.2
command:
- git
- clone
- --depth=1
- --branch=main
- https://github.com/myorg/myapp.git
- /workspace
volumeMounts:
- name: workspace
mountPath: /workspace
containers:
- name: kaniko-executor
image: martizih/kaniko:v1.26.4
args:
- --context=/workspace
- --dockerfile=/workspace/Dockerfile
- --destination=ghcr.io/myorg/myapp:$(date +%Y%m%d-%H%M%S)
- --cache=true
- --cache-repo=ghcr.io/myorg/myapp/cache
- --snapshot-mode=redo
- --use-new-run
volumeMounts:
- name: workspace
mountPath: /workspace
- name: docker-config
mountPath: /kaniko/.docker/
# Kaniko s'exécute en tant qu'utilisateur non-root (UID 1000)
securityContext:
runAsUser: 1000
runAsNonRoot: true
allowPrivilegeEscalation: false
volumes:
- name: workspace
emptyDir: {}
- name: docker-config
secret:
secretName: regcred
items:
- key: .dockerconfigjson
path: config.json

Créer le Secret pour le registry :

Fenêtre de terminal
kubectl create secret docker-registry regcred \
--docker-server=ghcr.io \
--docker-username=myuser \
--docker-password=ghp_xxxxxxxxxxxxx \
--namespace=ci-cd

Lancer le build :

Fenêtre de terminal
kubectl apply -f kaniko-pod.yaml -n ci-cd
# Suivre les logs en temps réel
kubectl logs -f kaniko-builder -c kaniko-executor -n ci-cd

Vérifier le succès : À la fin des logs, vous devez voir Pushing image to ghcr.io/myorg/myapp:<tag> suivi de Pushed.

Pour rebuilder automatiquement des images (ex: images de base mise à jour toutes les nuits) :

apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-rebuild
namespace: ci-cd
spec:
schedule: "0 2 * * *" # Tous les jours à 2h du matin
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
initContainers:
- name: git-clone
image: alpine/git:2.45.2
command:
- git
- clone
- --depth=1
- https://github.com/myorg/myapp.git
- /workspace
volumeMounts:
- name: workspace
mountPath: /workspace
containers:
- name: kaniko
image: martizih/kaniko:v1.26.4
args:
- --context=/workspace
- --destination=ghcr.io/myorg/myapp:nightly-$(date +%Y%m%d)
- --cache=true
- --cache-repo=ghcr.io/myorg/myapp/cache
volumeMounts:
- name: workspace
mountPath: /workspace
- name: docker-config
mountPath: /kaniko/.docker/
volumes:
- name: workspace
emptyDir: {}
- name: docker-config
secret:
secretName: regcred
items:
- key: .dockerconfigjson
path: config.json

Kaniko offre de nombreuses options pour optimiser les builds, gérer le cache et résoudre des cas d’usage spécifiques.

Le cache améliore drastiquement les temps de build en réutilisant les layers inchangés entre deux builds. Kaniko stocke le cache dans un registry OCI.

Activer le cache :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:1.0.0 \
--cache=true \
--cache-repo=ghcr.io/user/myapp/cache \
--cache-ttl=168h

Paramètres de configuration du cache : Le cache Kaniko fonctionne en stockant chaque layer OCI dans un registry dédié. Au prochain build, si le Dockerfile et le contexte sont identiques pour une instruction, Kaniko télécharge le layer depuis le cache au lieu de le reconstruire. Voici les options à maîtriser :

  • --cache=true : Active le cache (désactivé par défaut)
  • --cache-repo : Registry où stocker les layers cachés (doit être différent de l’image finale, utilisez un suffixe /cache)
  • --cache-ttl : Durée de validité du cache (défaut: 2 semaines = 336h, au-delà Kaniko ignore les layers et les reconstruit)

Comment ça fonctionne : Kaniko push chaque layer dans cache-repo. Au prochain build, si le Dockerfile et le contexte sont identiques pour une instruction, Kaniko réutilise le layer depuis le cache au lieu de le reconstruire.

Kaniko supporte les Dockerfile multi-stage comme Docker build. Utilisez --target pour builder une étape spécifique.

Dockerfile multi-stage :

# Étape de build
FROM golang:1.23-alpine3.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .
# Étape production (image minimale)
FROM alpine:3.21 AS production
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /usr/local/bin/
CMD ["server"]
# Étape debug (avec shell pour troubleshooting)
FROM production AS debug
RUN apk add --no-cache bash curl

Builder l’étape production :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:1.0.0 \
--target=production

Builder l’étape debug :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:1.0.0-debug \
--target=debug

Passez des variables dynamiques au Dockerfile avec --build-arg.

Dockerfile avec ARG :

ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-slim
ARG APP_VERSION=dev
LABEL version="${APP_VERSION}"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
WORKDIR /app
CMD ["python", "app.py"]

Build avec args personnalisés :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:2.1.0 \
--build-arg PYTHON_VERSION=3.11 \
--build-arg APP_VERSION=2.1.0

Par défaut, Kaniko push les images vers un registry. Pour sauvegarder localement en tar :

Exporter en tar (sans push) :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v "$PWD":/output \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=myapp:1.0.0 \
--no-push \
--tarPath=/output/myapp-1.0.0.tar

Cela crée myapp-1.0.0.tar (environ 6-10 MB pour une image Alpine de base) que vous pouvez charger avec :

Fenêtre de terminal
docker load < myapp-1.0.0.tar
# Sortie : Loaded image: myapp:1.0.0
# Vérifier que l'image est disponible
docker images | grep myapp
# myapp:1.0.0 ed5911d3a023 21.5MB 6.51MB

Push vers plusieurs registries simultanément :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:1.0.0 \
--destination=docker.io/user/myapp:1.0.0 \
--destination=harbor.example.com/library/myapp:1.0.0

Le mode snapshot détermine comment Kaniko détecte les changements du filesystem entre les layers. C’est un paramètre critique qui impacte directement la performance et la fiabilité du build. Kaniko doit savoir quels fichiers ont changé entre deux instructions RUN pour créer les bons layers OCI.

Modes disponibles (par ordre de fiabilité décroissante) :

  • full (défaut) : Analyse complète du filesystem à chaque layer (lent mais sûr) — scanne tous les fichiers, garantit la précision
  • redo (recommandé production) : Compare uniquement les fichiers modifiés depuis le dernier layer — 20-40% plus rapide que full, fiabilité ~99%
  • time : Compare les timestamps des fichiers (très rapide mais moins fiable) — risque de manquer des changements si les timestamps ne sont pas mis à jour

Utiliser le mode redo (recommandé production) :

Fenêtre de terminal
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
--context=/workspace \
--destination=ghcr.io/user/myapp:1.0.0 \
--snapshot-mode=redo

Gain de performance : Le mode redo réduit le temps de build de 20-40% sur des projets moyens/grands.

Kaniko respecte le fichier .dockerignore pour exclure des fichiers/dossiers du build context. Placer ce fichier à la racine de votre projet permet de réduire drastiquement la taille du context envoyé à Kaniko (parfois de 500 MB à 50 MB), ce qui accélère le build de plusieurs minutes. Voici un exemple complet couvrant les cas courants :

.dockerignore :

# Fichiers de développement
.git/
.github/
*.md
LICENSE
# Dépendances locales
node_modules/
__pycache__/
*.pyc
.venv/
# Logs et artifacts
*.log
*.tmp
dist/
build/

Cela réduit la taille du contexte envoyé à Kaniko et accélère le build.

Kaniko étant un outil userspace sans daemon, les erreurs sont généralement liées aux permissions, à l’authentification registry ou aux limitations du Dockerfile.

SymptômeCause probableSolution
error pushing to registry: UNAUTHORIZEDCredentials registry invalidesVérifier config.json, refaire docker login, vérifier les permissions du token
error building image: error resolving dockerfile pathContext ou Dockerfile path incorrectVérifier --context et --dockerfile, utiliser des chemins absolus dans le conteneur
COPY failed: stat /workspace/file: no such file or directoryFichier manquant dans le contextVérifier que le fichier existe, vérifier .dockerignore
error saving layer: error uploading layer: 413 Request Entity Too LargeLayer trop volumineux (> 1GB)Optimiser le Dockerfile (supprimer caches dans la même instruction RUN), utiliser multi-stage build
unsupported platform: linux/arm64Image de base non disponible pour l’architectureUtiliser --customPlatform ou changer l’image de base pour une variante multi-arch
Build très lent (> 10 min)Cache désactivé ou mode snapshot fullActiver --cache=true, utiliser --snapshot-mode=redo
panic: runtime error: invalid memory addressBug Kaniko (rare) ou Dockerfile invalideMettre à jour vers la dernière version v1.26.x, vérifier la syntaxe Dockerfile

Avant de debugger un problème, collectez les informations de base pour comprendre la configuration Kaniko et l’environnement d’exécution.

Fenêtre de terminal
# Version de Kaniko
docker run --rm martizih/kaniko:v1.26.4 version
# Sortie : Kaniko version : v1.26.4
# Test d'authentification registry
docker run --rm \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4 \
/kaniko/executor --help | grep "registry"
# Vérifier le contenu du context
docker run --rm \
-v "$PWD":/workspace \
martizih/kaniko:v1.26.4-debug \
/busybox/ls -laR /workspace
# Logs verbeux (mode debug)
docker run --rm \
-v "$PWD":/workspace \
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
martizih/kaniko:v1.26.4-debug \
--context=/workspace \
--destination=ghcr.io/user/myapp:debug \
--verbosity=debug \
--log-format=text

Image -debug : Contient des outils supplémentaires (shell, busybox) pour debugger interactivement :

Fenêtre de terminal
docker run --rm -it \
-v "$PWD":/workspace \
--entrypoint=/busybox/sh \
martizih/kaniko:v1.26.4-debug

Symptôme : error pushing image to ghcr.io/user/myapp:1.0.0: UNAUTHORIZED: authentication required

Diagnostic : Cette erreur signifie que Kaniko n’arrive pas à s’authentifier auprès du registry. Les causes possibles sont nombreuses : credentials manquants, token expiré, permissions insuffisantes, ou Secret Kubernetes mal configuré. Voici les vérifications à effectuer dans l’ordre :

  1. Vérifier que config.json existe et contient les credentials :

    Fenêtre de terminal
    cat ~/.docker/config.json

    Vous devez voir une entrée auths avec votre registry.

  2. Tester le login manuellement :

    Fenêtre de terminal
    docker login ghcr.io -u USERNAME
  3. Vérifier les permissions du token GitHub :

    • Allez dans Settings → Developer settings → Personal access tokens
    • Vérifiez que les scopes write:packages et read:packages sont activés
  4. Si vous utilisez un Secret Kubernetes, vérifier qu’il est correctement monté :

    Fenêtre de terminal
    kubectl get secret regcred -n ci-cd -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq

Si vos builds Kaniko prennent plus de 5-10 minutes alors que Docker build est rapide, plusieurs optimisations sont possibles. La cause la plus fréquente est le cache désactivé ou mal configuré, suivi d’un Dockerfile non optimisé pour le cache et d’un context trop volumineux. Voici les actions à mener dans l’ordre de priorité (du plus impactant au moins impactant) :

Checklist d’optimisation :

  1. Activer le cache (gain 40-70% sur builds incrémentaux) :

    Fenêtre de terminal
    --cache=true --cache-repo=ghcr.io/user/myapp/cache
  2. Utiliser le mode snapshot redo :

    Fenêtre de terminal
    --snapshot-mode=redo
  3. Optimiser le Dockerfile : Réduire le nombre de layers, grouper les commandes RUN :

    # ❌ Lent : 3 layers
    RUN apt-get update
    RUN apt-get install -y curl
    RUN apt-get clean
    # ✅ Rapide : 1 layer
    RUN apt-get update && \
    apt-get install -y curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
  4. Vérifier la taille du context : Utiliser .dockerignore pour exclure node_modules/, .git/, etc.

  5. Utiliser des images de base Alpine : Plus légères et plus rapides à télécharger.

Ces recommandations vous aideront à maximiser la sécurité, la performance et la maintenabilité de vos builds Kaniko en production.

La sécurité est l’avantage principal de Kaniko par rapport au Docker-in-Docker. Suivez ces pratiques pour renforcer davantage l’isolation et limiter les risques.

  1. Toujours utiliser des images versionnées

    # ❌ Risqué : version flottante
    image: martizih/kaniko:debug
    # ✅ Production : version pinnée
    image: martizih/kaniko:v1.26.4

    Cela garantit des builds reproductibles et évite les surprises lors des mises à jour.

  2. Configurer securityContext dans Kubernetes

    securityContext:
    runAsUser: 1000
    runAsNonRoot: true
    allowPrivilegeEscalation: false
    capabilities:
    drop:
    - ALL
    readOnlyRootFilesystem: false # Kaniko écrit dans /kaniko et /workspace
  3. Stocker les credentials dans des Secrets Kubernetes

    Fenêtre de terminal
    # Créer le secret
    kubectl create secret docker-registry regcred \
    --docker-server=ghcr.io \
    --docker-username=myuser \
    --docker-password=ghp_token \
    --namespace=ci-cd
    # Référencer dans le Pod
    volumes:
    - name: docker-config
    secret:
    secretName: regcred
  4. Scanner les images après le build

    Intégrez Trivy ou Grype pour détecter les vulnérabilités :

    # Dans GitLab CI après le build Kaniko
    scan-vulnerabilities:
    stage: security
    image: aquasec/trivy:0.58.1
    script:
    - trivy image --severity HIGH,CRITICAL ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}
    allow_failure: false

Les builds Kaniko peuvent être aussi rapides que Docker build avec les bonnes optimisations. Voici comment maximiser la vitesse et réduire l’utilisation des ressources.

  1. Activer le cache registry

    Fenêtre de terminal
    --cache=true \
    --cache-repo=ghcr.io/user/myapp/cache \
    --cache-ttl=336h

    Gain mesuré : 40-70% de réduction du temps sur les builds incrémentaux.

  2. Utiliser le mode snapshot optimisé

    Fenêtre de terminal
    --snapshot-mode=redo \
    --use-new-run

    --use-new-run améliore l’exécution des commandes RUN en utilisant un mode d’exécution optimisé.

  3. Paralléliser les builds multi-images

    Si vous avez plusieurs images à builder (frontend, backend, worker), lancez les builds Kaniko en parallèle dans des Pods différents ou des jobs CI/CD séparés.

  4. Limiter la taille du context avec .dockerignore

    Un context de 500 MB vs 50 MB peut faire la différence de 2-3 minutes sur le temps de copie.

  5. Utiliser des multi-stage builds

    Séparez les étapes de compilation et d’exécution pour réduire la taille de l’image finale et améliorer le cache.

    FROM golang:1.23-alpine AS builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download # ← Layer caché si go.mod/go.sum inchangés
    COPY . .
    RUN go build -o server .
    FROM alpine:3.21
    COPY --from=builder /app/server /usr/local/bin/
    CMD ["server"]

Des builds reproductibles et bien documentés facilitent le debugging, la collaboration et l’évolution du projet au fil du temps.

  1. Versionner les images de base

    # ❌ Non reproductible
    FROM python:3-slim
    # ✅ Reproductible
    FROM python:3.12.8-slim-bookworm
  2. Ajouter des labels OCI pour la traçabilité

    LABEL org.opencontainers.image.source="https://github.com/myorg/myapp"
    LABEL org.opencontainers.image.version="1.2.0"
    LABEL org.opencontainers.image.created="2026-01-22T10:00:00Z"
    LABEL org.opencontainers.image.revision="${GIT_COMMIT}"

    Dans GitLab CI, passez le commit SHA dynamiquement :

    script:
    - /kaniko/executor
    --context "${CI_PROJECT_DIR}"
    --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
    --build-arg GIT_COMMIT="${CI_COMMIT_SHA}"
  3. Documenter les builds dans un README ou ADR

    Expliquez pourquoi Kaniko a été choisi, quelles sont les configurations spécifiques, et comment reproduire les builds localement.

  4. Centraliser la configuration dans un Makefile ou script

    # Makefile
    IMAGE := ghcr.io/myorg/myapp
    VERSION := $(shell git describe --tags --always)
    .PHONY: build
    build:
    docker run --rm \
    -v $(PWD):/workspace \
    -v ~/.docker/config.json:/kaniko/.docker/config.json:ro \
    martizih/kaniko:v1.26.4 \
    --context=/workspace \
    --destination=$(IMAGE):$(VERSION) \
    --cache=true \
    --cache-repo=$(IMAGE)/cache \
    --snapshot-mode=redo
    .PHONY: build-debug
    build-debug:
    docker run --rm \
    -v $(PWD):/workspace \
    martizih/kaniko:v1.26.4-debug \
    --context=/workspace \
    --destination=$(IMAGE):debug \
    --no-push \
    --verbosity=debug

    Usage : make build ou make build-debug.

  • Kaniko build des images OCI sans daemon Docker, éliminant les risques de sécurité du Docker-in-Docker
  • Fork actif osscontainertools/kaniko (v1.26.4, janvier 2026) après l’archivage de GoogleContainerTools/kaniko en juin 2025
  • Idéal pour Kubernetes et CI/CD (GitLab CI, GitHub Actions, Tekton) : Pods standard, pas de privilèges root
  • Cache registry obligatoire pour des builds rapides : --cache=true --cache-repo=registry/image/cache
  • Authentification via config.json monté en volume ou Secret Kubernetes
  • Snapshot mode redo + --use-new-run pour optimiser la performance
  • Multi-stage builds supportés avec --target pour builder des étapes spécifiques
  • Limitations mineures : ~5% des Dockerfiles complexes (ONBUILD, certains hérédités) non supportés
  • Alternative à Buildah : Kaniko = userspace pur, Buildah = rootless natif (plus flexible mais nécessite vfs ou fuse-overlayfs)

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.