9

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.

Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267

1 Answers1

14

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"]
Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267
  • 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) – Marcos Pereira Mar 17 '23 at 17:21
  • The suggestion to use `SHELL ["/bin/bash", "-o", "pipefail", "-c"]` is not covered there though, but much appreciated that you did it. See also https://github.com/moby/moby/pull/7489#issuecomment-816858450 , https://docs.docker.com/engine/reference/builder/#shell – Jason Kleban Aug 01 '23 at 22:05