bash 如何通过 docker run 将参数传递给 Shell 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32727594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass arguments to Shell Script through docker run
提问by Akash Mehta
I am new to the docker world. I have to invoke a shell script that takes command line arguments through a docker container. Ex: My shell script looks like:
我是 docker 世界的新手。我必须调用一个通过 docker 容器获取命令行参数的 shell 脚本。例如:我的 shell 脚本如下所示:
#!bin/bash
echo
Dockerfile looks like this:
Dockerfile 看起来像这样:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
I am not sure how to pass the arguments while running the container
我不确定如何在运行容器时传递参数
采纳答案by BMW
Use the same file.sh
使用相同 file.sh
#!/bin/bash
echo
Build the image using the existing Dockerfile:
使用现有的 Dockerfile 构建镜像:
docker build -t test .
Run the image with arguments abc
or xyz
or something else.
使用参数abc
或xyz
其他东西运行图像。
docker run -ti test /file.sh abc
docker run -ti test /file.sh xyz
回答by Partly Cloudy
with this script in file.sh
用这个脚本 file.sh
#!/bin/bash
echo Your container args are: "$@"
and this Dockerfile
和这个 Dockerfile
FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]
you should be able to:
你应该能够:
% docker build -t test .
% docker run test hello world
Your container args are: hello world
回答by Michael
With Docker, the proper way to pass this sort of information is through environment variables.
对于 Docker,传递此类信息的正确方法是通过环境变量。
So with the same Dockerfile, change the script to
因此,使用相同的 Dockerfile,将脚本更改为
#!/bin/bash
echo $FOO
After building, use the following docker command:
构建完成后,使用以下 docker 命令:
docker run -e FOO="hello world!" test
回答by BMitch
There are a few things interacting here:
这里有一些交互作用:
docker run your_image arg1 arg2
will replace the value ofCMD
witharg1 arg2
. That's a full replacement of the CMD, not appending more values to it. This is why you often seedocker run some_image /bin/bash
to run a bash shell in the container.When you have both an ENTRYPOINT and a CMD value defined, docker starts the container by concatenating the two and running that concatenated command. So if you define your entrypoint to be
file.sh
, you can now run the container with additional args that will be passed as args tofile.sh
.Entrypoints and Commands in docker have two syntaxes, a string syntax that will launch a shell, and a json syntax that will perform an exec. The shell is useful to handle things like IO redirection, chaining multiple commands together (with things like
&&
), variable substitution, etc. However, that shell gets in the way with signal handling (if you've ever seen a 10 second delay to stop a container, this is often the cause) and with concatenating an entrypoint and command together. If you define your entrypoint as a string, it would run/bin/sh -c "file.sh"
, which alone is fine. But if you have a command defined as a string too, you'll see something like/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"
as the command being launched inside your container, not so good. See the table here for more on how these two options interactThe shell
-c
option only takes a single argument. Everything after that would get passed as$1
,$2
, etc, to that single argument, but not into an embedded shell script unless you explicitly passed the args. I.e./bin/sh -c "file.sh $1 $2" "arg1" "arg2"
would work, but/bin/sh -c "file.sh" "arg1" "arg2"
would not sincefile.sh
would be called with no args.
docker run your_image arg1 arg2
将替代的价值CMD
与arg1 arg2
。这是对 CMD 的完全替换,而不是为其附加更多值。这就是为什么你经常看到docker run some_image /bin/bash
在容器中运行 bash shell 的原因。当您同时定义了 ENTRYPOINT 和 CMD 值时,docker 通过将两者连接并运行该连接命令来启动容器。因此,如果您将入口点定义为
file.sh
,则现在可以使用将作为 args 传递给 的其他 args 运行容器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
会在没有参数的情况下被调用。
Putting that all together, the common design is:
将所有这些放在一起,共同的设计是:
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"]
And you then run that with:
然后你运行它:
docker run your_image arg1 arg2
There's a fair bit more detail on this at:
对此有更多详细信息:
回答by jkh
What I have is a script file that actually runs things. This scrip file might be relatively complicated. Let's call it "run_container". This script takes arguments from the command line:
我拥有的是一个实际运行的脚本文件。这个脚本文件可能比较复杂。我们称之为“run_container”。此脚本从命令行获取参数:
run_container p1 p2 p3
A simple run_container might be:
一个简单的 run_container 可能是:
#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"
What I want to do is, after "dockering" this I would like to be able to startup this container with the parameters on the docker command line like this:
我想要做的是,在“dockering”之后,我希望能够使用 docker 命令行上的参数启动这个容器,如下所示:
docker run image_name p1 p2 p3
and have the run_container script be run with p1 p2 p3 as the parameters.
并让 run_container 脚本以 p1 p2 p3 作为参数运行。
This is my solution:
这是我的解决方案:
Dockerfile:
Dockerfile:
FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]
回答by Gilles Quenot
If you want to run it @build time :
如果你想运行它 @build time :
CMD /bin/bash /file.sh arg1
if you want to run it @run time :
如果你想在@run time 上运行它:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
Then in the host shell
然后在主机外壳中
docker build -t test .
docker run -i -t test
回答by wagnermarques
Another option...
另外一个选项...
To make this works
为了使这个工作
docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"
in dockerfile
在 dockerfile 中
ENTRYPOINT ["/entrypoint.sh"]
in entrypoint.sh
在入口点.sh
#!/bin/sh
entrypoint_params=
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