17

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.

1 Answer 1

29

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"]
Sign up to request clarification or add additional context in comments.

3 Comments

How would you set multiple values, such as pipefail and nounset, without the repeating the set command? (as you are instead passing these as an ` -o` flag to the shell directly)
The suggestion to use SHELL ["/bin/bash", "-o", "pipefail", "-c"] is not covered there though, but much appreciated that you did it. See also github.com/moby/moby/pull/7489#issuecomment-816858450 , docs.docker.com/engine/reference/builder/#shell
In addition to -o, I recommend to also use the -u and -e options like this: SHELL ["/bin/bash", "-eou", "pipefail", "-c"]. See here for an explanation of those flags.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.