Search code examples
dockersh

Using "set -eux pipefail" in docker CMD


I have simple dockerfile

FROM alpine:latest

This is my docker run command

docker run <container-name> \
sh -c """set -eux pipefail && \
temp | sed 's/temp/perma/g'"""

This is the output

+ temp
sh: temp: not found
+ sed s/temp/perma/g

But, the return code of the above docker run is 0.

Even though I have a pipefail using set, why does docker return 0?

Though not shown here, if there were any subsequent commands after the sed command which were chained with &&, they will be executed.

Why does set -eux pipefail not work ?


Solution

  • Remember that one of the things that makes Alpine small is that it doesn't include the full GNU tool set you normally get on Linux, but instead a minimal implementation called BusyBox. When you're using the shell, you get what's supported in the POSIX shell specification but not much more.

    In particular, POSIX-standard set(1) doesn't support bash's pipefail option.

    As noted in a comment, you also need a -o option to specify long-form shell options. Without -o, this has the effect of setting positional arguments instead.

    $ docker run --rm alpine \
        sh -c 'echo "one: $1"; set -eux pipefail; echo "one: $1"'
    + echo 'one: pipefail'
    one:
    one: pipefail
    

    If you really need extended GNU bash functionality, you need to apk add bash to install bash, or to use a base image like debian or ubuntu that already includes it. Make sure to explicitly say bash -c or #!/bin/bash so you're specifying the right shell.