Running Docker-in-Docker (dind) in a CI pipeline inside Kubernetes means mounting /var/run/docker.sock from the node into the builder container, giving it root access to the host. Any code built in that pipeline can potentially escape the container — this is not a hypothetical threat but a real one, similar to CVE-2019-5736. We solve this problem with Kaniko — a tool for building Docker images entirely in userspace without a Docker daemon. Our engineers have implemented Kaniko in 50+ projects, ensuring isolation and build speed. Thanks to layer caching, CI infrastructure costs are reduced by 40–50%, and ROI is achieved within the first month.
How Kaniko builds images without Docker daemon
Kaniko executes each Dockerfile instruction in an isolated container. Instead of using an overlay filesystem, it snapshots file system changes after each RUN/COPY command and creates layers manually. It runs as a regular user and does not require --privileged. This makes builds safe even in multi-tenant clusters. According to the project, Kaniko is used in production by thousands of teams, and its code is actively maintained by the community.
Step-by-step Kaniko setup in GitLab CI
-
Prepare a Secret with credentials. Create a Kubernetes Secret of type
docker-registryor assemble aconfig.jsonwith authentication to your registry. -
Define the Kaniko image in CI. Use
gcr.io/kaniko-project/executor:v1.23.0-debugand pass the necessary arguments. - Enable caching. Add flags
--cache=trueand--cache-repoto speed up repeated builds. - Run the build. Kaniko will build the image and push it to the registry without mounting docker.sock.
Minimal example:
---
build:
image:
name: gcr.io/kaniko-project/executor:v1.23.0-debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n $CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD | base64)\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --cache=true --cache-repo $CI_REGISTRY_IMAGE/cache
What Kaniko caching provides
--cache=true — Kaniko caches intermediate layers in a separate repository. On repeated builds with the same instructions and context, it reuses layers from the cache. This reduces build time for images with unchanged dependencies. In our projects, time savings reach 70% on repeated builds, cutting CI costs by an average of 40-50%. We also configure cache retention policies to avoid overflowing the registry.
Snapshot mode options:
| Mode | Description | Speed | Accuracy |
|---|---|---|---|
| full | Default: compares entire filesystem | Fast | Low (may miss changes) |
| redo | Re-executes instruction and compares with previous layer | Slower | High |
For most projects, full is sufficient, but if the image builds incorrectly, switch to redo.
Building as a Kubernetes Job
To use Kaniko directly in the cluster (not in GitLab Runner), launch a Kubernetes Job:
---
apiVersion: batch/v1
kind: Job
metadata:
name: build-my-app
spec:
template:
spec:
restartPolicy: Never
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:v1.23.0
args:
- "--dockerfile=/workspace/Dockerfile"
- "--context=git://github.com/my-org/my-app#main"
- "--destination=my-registry.io/my-app:latest"
- "--cache=true"
- "--cache-repo=my-registry.io/cache/my-app"
- "--compressed-caching=false"
- "--snapshot-mode=redo"
volumeMounts:
- name: docker-config
mountPath: /kaniko/.docker
volumes:
- name: docker-config
secret:
secretName: registry-credentials
items:
- key: .dockerconfigjson
path: config.json
---
--context=git:// — Kaniko clones the repository directly, no PVC with sources needed. For private repositories via SSH or with a token: --git git_token=<token>. --snapshot-mode=redo — more accurate (and slightly slower) mode than full. Used when the image differs from expected in default mode.
Common issues and solutions
- Error
error pushing image: failed to pushwith 401 —config.jsonin/kaniko/.docker/exists but format is wrong. Kaniko strictly expects{"auths":{"registry":{"auth":"base64(user:pass)"}}}. If the registry uses Docker Credential Helper (credsStore) — Kaniko does not support it, explicitauthis required. - Slow build without cache — Kaniko does not use cache by default.
--cache=true+--cache-repoare mandatory for acceleration. The first build is always slow — it fills the cache. -
OCI runtime exec failed: exec format error— trying to run an ARM image on an AMD64 node or vice versa. For multi-platform builds, Kaniko supports--custom-platform linux/arm64, but builds are emulated via QEMU, which is significantly slower than native. - Large
/workspace— Kaniko copies the entire build context into memory before building. A repository with binaries, node_modules, or large fixtures may exhaust the pod's memory. Solution:.dockerignoreexcluding everything unnecessary.
How Kaniko handles multi-platform builds
Kaniko can build images for other architectures using the --custom-platform flag. However, emulation via QEMU slows down the process by 2-3 times. For production, use native nodes or build farms for each architecture. An alternative is buildx, but it requires a Docker daemon.
Comparison with buildah and img
| Tool | Approach | Privileges | Speed |
|---|---|---|---|
| Kaniko | userspace snapshotting | none | medium |
| buildah | overlayfs in user namespace | none (newer versions) | faster |
| img | runc + snapshotter | none | faster |
| Docker DinD | docker daemon | root or privileged | fast |
Kaniko is chosen for its simplicity and wide CI system support. buildah is used when speed is needed and user namespace setup on nodes is acceptable.
What is included in Kaniko implementation
We provide a full cycle: audit of current infrastructure, secure pipeline design, registry access configuration with minimal privileges, migration of existing builds, caching optimization, documentation, and team training. As a result, you receive:
- A working CI/CD with Kaniko in your infrastructure.
- Configured caching with retention policy.
- Documentation for maintenance and common errors.
- Recommendations for further optimization.
Timeline — one to three days. Cost is calculated after infrastructure audit. Order Kaniko implementation with a security guarantee. Get a consultation — we will assess your project and propose a secure Kaniko implementation.
Every second CI build in your project will be significantly faster, and risks associated with mounting docker.sock will become a thing of the past. Contact us to discuss Kaniko implementation and get a personalized migration plan.







