[英]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 .
使用参数abc
或xyz
或其他参数运行图像。
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
这里有一些交互作用:
docker run your_image arg1 arg2
将取代的价值CMD
与arg1 arg2
。 这是对 CMD 的完全替换,而不是为其附加更多值。 这就是为什么你经常看到docker run some_image /bin/bash
在容器中运行一个 bash shell。
当您同时定义了 ENTRYPOINT 和 CMD 值时,docker 通过将两者连接并运行该连接命令来启动容器。 因此,如果您将入口点定义为file.sh
,则现在可以运行带有附加参数的容器,这些参数将作为参数传递给file.sh
。
docker 中的入口点和命令有两种语法,一种是启动 shell 的字符串语法,另一种是执行 exec 的 json 语法。 shell 可用于处理诸如 IO 重定向、将多个命令链接在一起(使用&&
东西)、变量替换等。但是,该 shell 会妨碍信号处理(如果您曾经见过 10 秒延迟到停止容器,这通常是原因)并将入口点和命令连接在一起。 如果您将入口点定义为字符串,它将运行/bin/sh -c "file.sh"
,这本身就很好。 但是如果你也有一个定义为字符串的命令,你会看到像/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"
这样的命令在你的容器内启动,而不是这样好的。 有关这两个选项如何相互作用的更多信息,请参阅此处的表格
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.