繁体   English   中英

如何通过 arguments 到 Shell 脚本通过 docker 运行

[英]How to pass arguments to Shell Script through docker run

我是 docker 世界的新手。 我必须调用 shell 脚本,该脚本通过 docker 容器获取命令行 arguments。 例如:我的 shell 脚本如下所示:

#!bin/bash
echo $1

Dockerfile 看起来像这样:

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh

我不确定在运行容器时如何通过 arguments

file.sh使用此脚本

#!/bin/bash
echo Your container args are: "$@"

和这个Dockerfile

FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]

你应该能够:

% docker build -t test .
% docker run test hello world
Your container args are: hello world

使用同一个文件file.sh

#!/bin/bash
echo $1

使用现有的 Dockerfile 构建镜像:

docker build -t test .

使用参数abcxyz或其他参数运行图像。

docker run -ti --rm test /file.sh abc

docker run -ti --rm test /file.sh xyz

对于 Docker,传递此类信息的正确方法是通过环境变量。

因此,使用相同的 Dockerfile,将脚本更改为

#!/bin/bash
echo $FOO

构建完成后,使用以下 docker 命令:

docker run -e FOO="hello world!" test

这里有一些交互作用:

  1. docker run your_image arg1 arg2将取代的价值CMDarg1 arg2 这是对 CMD 的完全替换,而不是为其附加更多值。 这就是为什么你经常看到docker run some_image /bin/bash在容器中运行一个 bash shell。

  2. 当您同时定义了 ENTRYPOINT 和 CMD 值时,docker 通过将两者连接并运行该连接命令来启动容器。 因此,如果您将入口点定义为file.sh ,则现在可以运行带有附加参数的容器,这些参数将作为参数传递给file.sh

  3. docker 中的入口点和命令有两种语法,一种是启动 shell 的字符串语法,另一种是执行 exec 的 json 语法。 shell 可用于处理诸如 IO 重定向、将多个命令链接在一起(使用&&东西)、变量替换等。但是,该 shell 会妨碍信号处理(如果您曾经见过 10 秒延迟到停止容器,这通常是原因)并将入口点和命令连接在一起。 如果您将入口点定义为字符串,它将运行/bin/sh -c "file.sh" ,这本身就很好。 但是如果你也有一个定义为字符串的命令,你会看到像/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"这样的命令在你的容器内启动,而不是这样好的。 有关这两个选项如何相互作用的更多信息,请参阅此处的表格

  4. shell -c选项只接受一个参数。 之后的所有内容都将作为$1$2等传递给该单个参数,但不会传递到嵌入式 shell 脚本中,除非您明确传递了 args。 /bin/sh -c "file.sh $1 $2" "arg1" "arg2"会工作,但/bin/sh -c "file.sh" "arg1" "arg2"不会,因为file.sh会被调用没有参数。

将所有这些放在一起,共同的设计是:

FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a shell being used to run the line.
ENTRYPOINT ["file.sh"]

然后你运行它:

docker run your_image arg1 arg2

对此有更多详细信息:

我拥有的是一个实际运行的脚本文件。 这个脚本文件可能比较复杂。 我们称之为“run_container”。 此脚本从命令行获取参数:

run_container p1 p2 p3

一个简单的 run_container 可能是:

#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"

我想要做的是,在“dockering”之后,我希望能够使用 docker 命令行上的参数启动这个容器,如下所示:

docker run image_name p1 p2 p3

并让 run_container 脚本以 p1 p2 p3 作为参数运行。

这是我的解决方案:

Dockerfile:

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]

如果你想运行它 @build time :

CMD /bin/bash /file.sh arg1

如果你想在@run time 上运行它:

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]

然后在主机外壳中

docker build -t test .
docker run -i -t test

另外一个选项...

为了使这个工作

docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"

在 dockerfile 中

ENTRYPOINT ["/entrypoint.sh"]

在入口点.sh

#!/bin/sh

entrypoint_params=$1
printf "==>[entrypoint.sh] %s\n" "entry_point_param is $entrypoint_params"

PARAM1=$(echo $entrypoint_params | cut -d':' -f1) # output is 1 must be 'bash' it     will be tested    
PARAM2=$(echo $entrypoint_params | cut -d':' -f2) # the real command separated by     &&

printf "==>[entrypoint.sh] %s\n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s\n" "PARAM2=$PARAM2"

if [ "$PARAM1" = "bash" ];
then
    printf "==>[entrypoint.sh] %s\n" "about to running $PARAM2 command"
    echo $PARAM2 | tr '&&' '\n' | while read cmd; do
        $cmd
    done    
fi

我想使用 ENTRYPOINT 的字符串版本,所以我可以使用交互式 shell。

FROM docker.io/ubuntu
...
ENTRYPOINT python -m server "$@"

然后运行命令(注意-- ):

docker run -it server -- --my_server_flag

其工作方式是ENTRYPOINT的字符串版本运行 shell,命令指定为-c标志的值。 Arguments 传递给 shell 之后--作为 arguments 提供给"$@"所在的命令。 请参阅此处的表格: https://tldp.org/LDP/abs/html/options.html

(感谢@jkh 和@BMitch 的回答帮助我了解正在发生的事情。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM