kaniko: Missing or partial support for pattern substition in variable references (e.g. in RUN)

Here is a minimal working example that reproduces this issue with across different Kaniko versions, with and without caching. (The script assumes bash and a terminal capable of highlighting).

cd "$(mktemp -d)"
{
    echo FROM alpine
    echo RUN var=a-b\; echo \${var/-//}
} | tee Dockerfile
e=$'\x1b' w=/workspace k=gcr.io/kaniko-project/executor
for i in {17..21}
do for c in "" "--cache --cache-repo -"
do echo "$e[33;1m$i:${c:2:6}$e[0m"
    docker run --rm -it -v "$PWD":$w $k:v0.$i.0 --no-push $c |
        sed "s/.*missing.*/$e[31;1m&$e[0m/"
    done
done
rm -vfr "$PWD"
cd -

The output is omitted for brevity (just run the script). The results are mixed. The following table provides a summary.

version cache no-cache
v0.17.0 OK OK
v0.18.0 OK OK
v0.19.0 KO KO
v0.20.0 OK KO
v0.21.0 OK KO

Essentially, v0.19.0 is broken irrespective of caching, while earlier versions appear to be fine, and later versions only break when caching is turned on.

The last and likely most relevant part of the compounded error comes from this line

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 43
  • Comments: 21 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I also ran int this issue with:

RUN something --version="release-${APP_VERSION%.*}"

A workaround with

ARG APP_VERSION_MAJMIN=${APP_VERSION%.*}

just gave me: missing ':' in substitution. The SHELL used was [“bash”]

It would be nyce to fix it.

Still happen on 1.7.0 kaniko version with cache. Any plan to fix it?

@tushar-door you can work around by moving the problematic lines to a shell script

Still an issue in v1.2.0. For example, the parameter expansion "${buildArch##*-}" works in Docker build, but not in Kaniko.

Please fix this bug. Its annoying as hell and makes it unusable

Hi all!
I found the promblem here.
Where cache is use we need get checksum before execute RUN instruction. For that need interpolate all variable of shell (ARG or ENV in Dockerfile can be new and we have to consider this). Lex shell library which used for this case support only syntax: $var or ${var} or ${var:(+|-|?)word}. Any other bash syntax will return “missing ‘:’ in substitution” Now can use only half sh syntax.

I found the easiest and most obvious workaround is to do the substitution with an if. eg.

-RUN curl --location --output /envsubst "https://github.com/a8m/envsubst/releases/download/v${ENVSUBST_VERSION}/envsubst-${TARGETOS}-${TARGETARCH/amd64/x86_64}" && \
+RUN if [ "$TARGETARCH" = "amd64" ]; then TARGETARCH=x86_64; fi && \
+    curl --location --output /envsubst "https://github.com/a8m/envsubst/releases/download/v${ENVSUBST_VERSION}/envsubst-${TARGETOS}-${TARGETARCH}" && \

Another workaround: something $(sh -c 'echo ${APP_VERSION%-*}') instead of something ${APP_VERSION%-*}. Pretty annoying…

This issue is still present when building with cache on gcr.io/kaniko-project/executor:latest 1c812ffa8ec1.

I am seeing the same issue. I am having to move out all complex shell parameter expansions out of the docker file and plug them in through build args. These expansions should be handled by the shell in a shell version of the RUN command, but Kaniko cache seems to be unaware of that.

A more local (but still pretty lame…) workaround may be to reformulate the expansions using command substitution and a pipeline (as in $(echo "$buildArch" | grep -o '[^-]*$') instead of ${buildArch##*-}), which Kaniko at least seems not to choke on.