dockerfilelinthadolint

DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it


I have a Dockerfile

FROM strimzi/kafka:0.20.1-kafka-2.6.0

USER root:root
RUN mkdir -p /opt/kafka/plugins/debezium
# Download, unpack, and place the debezium-connector-postgres folder into the /opt/kafka/plugins/debezium directory
RUN curl -s https://repo1.maven.org/maven2/io/debezium/debezium-connector-postgres/1.7.0.Final/debezium-connector-postgres-1.7.0.Final-plugin.tar.gz | tar xvz --transform 's/debezium-connector-postgres/debezium/' --directory /opt/kafka/plugins/
USER 1001

When I use hadolint on it by

hadolint Dockerfile

I got warning

Dockerfile:6 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check

I know I have a pipe | in the line started with RUN.

However, I still really don't know how to fix based on this warning.


Solution

  • Oh, just found the solution in the wiki page at https://github.com/hadolint/hadolint/wiki/DL4006

    Here is my fixed version:

    FROM strimzi/kafka:0.20.1-kafka-2.6.0
    
    USER root:root
    RUN mkdir -p /opt/kafka/plugins/debezium
    # Download, unpack, and place the debezium-connector-postgres folder into the /opt/kafka/plugins/debezium directory
    SHELL ["/bin/bash", "-o", "pipefail", "-c"]
    RUN curl -s https://repo1.maven.org/maven2/io/debezium/debezium-connector-postgres/1.7.0.Final/debezium-connector-postgres-1.7.0.Final-plugin.tar.gz | tar xvz --transform 's/debezium-connector-postgres/debezium/' --directory /opt/kafka/plugins/
    USER 1001
    

    The reason adding SHELL ["/bin/bash", "-o", "pipefail", "-c"] is at https://github.com/docker/docker.github.io/blob/master/develop/develop-images/dockerfile_best-practices.md#using-pipes

    Below is a copy:


    Some RUN commands depend on the ability to pipe the output of one command into another, using the pipe character (|), as in the following example:

    RUN wget -O - https://some.site | wc -l > /number
    

    Docker executes these commands using the /bin/sh -c interpreter, which only evaluates the exit code of the last operation in the pipe to determine success. In the example above this build step succeeds and produces a new image so long as the wc -l command succeeds, even if the wget command fails.

    If you want the command to fail due to an error at any stage in the pipe, prepend set -o pipefail && to ensure that an unexpected error prevents the build from inadvertently succeeding. For example:

    RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
    

    Not all shells support the -o pipefail option.

    In cases such as the dash shell on Debian-based images, consider using the exec form of RUN to explicitly choose a shell that does support the pipefail option. For example:

    RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]