Kaniko "error pushing image ... UNAUTHORIZED" (missing config.json) in CI
Kaniko built the image but the registry rejected the push with UNAUTHORIZED. Kaniko reads credentials from /kaniko/.docker/config.json; if that file is absent or has no auth entry for the destination registry, the push is anonymous and denied.
What this error means
Kaniko finishes building, then fails with "error pushing image: failed to push to destination registry.example.com/app:latest: UNAUTHORIZED: authentication required".
error pushing image: failed to push to destination registry.example.com/app:latest:
UNAUTHORIZED: authentication required; [map[Action:pull Class: Name:app Type:repository]]Common causes
No /kaniko/.docker/config.json with the registry auth
Kaniko does not run a docker login; it reads a Docker config file. If that file is missing or lacks an auths entry for the destination host, the push has no credentials.
The credential is for a different registry host
The auths key must exactly match the destination registry hostname. A mismatch (for example docker.io versus registry.example.com) means no credential applies.
How to fix it
Write a config.json with a base64 auth entry
- Base64-encode
user:tokenfor the destination registry. - Write it to
/kaniko/.docker/config.jsonbefore running the executor. - Confirm the
authskey matches the destination hostname exactly.
mkdir -p /kaniko/.docker
echo "{\"auths\":{\"registry.example.com\":{\"auth\":\"$(printf '%s' "$CI_USER:$CI_TOKEN" | base64 -w0)\"}}}" \
> /kaniko/.docker/config.jsonFor GitLab, use the built-in CI credentials
GitLab CI exposes $CI_REGISTRY, $CI_REGISTRY_USER, and $CI_REGISTRY_PASSWORD; write them into the Kaniko config.
echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf '%s' "${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" \
> /kaniko/.docker/config.jsonHow to prevent it
- Provision /kaniko/.docker/config.json in every Kaniko job before the executor runs.
- Match the auths hostname to the exact --destination registry.
- Store the registry token as a masked CI variable, never in the image.