问题描述
这真的很简单:我正在尝试构建一个 docker 映像,其中入口点接收传递的 args。当我使用 bash
shell 时,它可以工作。当我使用 sh
附带的 alpine
时,它不会扩展;我认为这是因为 sh
根本不需要参数
这可能吗?还有,怎么样?
这不起作用;意味着 docker run -it myimage arg1 arg2
不会像 arg1 arg2
要求的那样收到 ${@}
。我希望 gradlew
会被调用为 ./gradlew arg1 arg2
FROM openjdk:8u212-jre-alpine
RUN apk add --no-cache jq openjdk8 python3 \
&& pip3 install --upgrade pip && pip3 install yq
copY . /root
workdir /root
RUN ./gradlew dependencies &> /dev/null
ENTRYPOINT [ "sh","-c","./gradlew ${@}" ]
这样做:
FROM gradle
copY . /home/gradle
RUN ./gradlew -v && ./gradlew dependencies &> /dev/null
ENTRYPOINT [ "bash","./gradlew ${@}" ]
当我深入了解 sh
的真正含义时:
/bin # which sh
/bin/sh
/bin # ls -al /bin/sh
lrwxrwxrwx 1 root root 12 May 9 2019 /bin/sh -> /bin/busyBox
解决方法
我对“gradle”一无所知,因此让我们将您对 gradlew
的调用替换为 echo
语句以进行诊断:
FROM openjdk:8u212-jre-alpine
ENTRYPOINT [ "sh","-c","echo ${@}" ]
如果我构建一个名为 cbtest
的映像并像这样运行它:
docker run --rm cbtest arg1 arg2
我得到的输出:
arg2
这意味着它主要是有效的,除非我在评论中指出你失去了你的第一个论点。如果我们查看 bash(1)
手册页,我们会发现:
-c If the -c option is present,then commands are read from the
first non-option argument command_string. If there are
arguments after the command_string,the first argument is
assigned to $0 and any remaining argu‐ ments are assigned to the
positional parameters. The assignment to $0 sets the name of the
shell,which is used in warning and error messages.
关键短语是第一个参数分配给 $0。这
参数 $0
是当前正在运行的程序的名称,而不是
而不是程序的参数。您需要将 --
添加到您的 sh
指示它应该停止尝试解析参数的命令行
并将所有内容作为参数传递给被调用的脚本。再次来自手册页:
-- A -- signals the end of options and disables further option
processing. Any arguments after the -- are treated as filenames
and arguments. An argument of - is equivalent to --.
这给了我们:
FROM openjdk:8u212-jre-alpine
ENTRYPOINT [ "sh","echo ${@}","--" ]
如果我运行与上面相同的命令,我现在得到:
arg1 arg2
那太好了。
我在评论中提到您滥用了 ${@}
变量
因为你没有引用它。你可能认为你是,但是
/bin/sh
你调用的对这些引用一无所知;这
传递给shell的命令很简单:
./gradlew ${@}
...${@}
周围没有引号。让我们稍微修改一下脚本
我们可以看到差异;考虑这个脚本:
FROM openjdk:8u212-jre-alpine
ENTRYPOINT [ "sh","for arg in ${@}; do echo $arg; done","--" ]
如果我像这样运行图像:
docker run --rm cbtest "arg with spaces" "second arg"
我得到的输出:
arg
with
spaces
second
arg
如您所见,脚本看到的是五个参数而不是两个。 我们可以通过适当的引用来解决这个问题:
FROM openjdk:8u212-jre-alpine
ENTRYPOINT [ "sh","for arg in \"${@}\"; do echo $arg; done","--" ]
给定以上输入产生的结果:
arg with spaces
second arg
所以您的 ENTRYPOINT
应该看起来像这样:
ENTRYPOINT [ "sh","./gradlew \"${@}\"","--" ]