我是码头工人的新手。我必须调用一个shell脚本,它通过docker容器接受命令行参数。 示例:我的shell脚本看起来像:
#!bin/bash
echo $1
Dockerfile是这样的:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定在运行容器时如何传递参数
我是码头工人的新手。我必须调用一个shell脚本,它通过docker容器接受命令行参数。 示例:我的shell脚本看起来像:
#!bin/bash
echo $1
Dockerfile是这样的:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定在运行容器时如何传递参数
如果你想@build time运行它:
CMD /bin/bash /file.sh arg1
如果你想运行它@运行时:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
然后在主壳层
docker build -t test .
docker run -i -t test
使用相同的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
我所拥有的是一个实际运行的脚本文件。这个票据文件可能相对复杂。让我们称它为“run_container”。这个脚本从命令行获取参数:
run_container p1 p2 p3
一个简单的run_container可能是:
#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"
我想做的是,在“dockering”之后,我希望能够用docker命令行上的参数启动这个容器,就像这样:
docker run image_name p1 p2 p3
并以p1 p2 p3作为参数运行run_container脚本。
这是我的解决方案:
Dockerfile:
FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]
使用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
这里有一些相互作用的东西:
docker run your_image arg1 arg2 will replace the value of CMD with arg1 arg2. That's a full replacement of the CMD, not appending more values to it. This is why you often see docker 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 to file.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 interact The 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 since file.sh would be called with no args.
把所有这些放在一起,常见的设计是:
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
这里有更多的细节:
https://docs.docker.com/engine/reference/run/#cmd-default-command-or-options https://docs.docker.com/engine/reference/builder/#exec-form-entrypoint-example
另一种选择……
为了让它起作用
docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"
在dockerfile
ENTRYPOINT ["/entrypoint.sh"]
在entrypoint.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标志的值。在——之后传递给shell的参数作为“$@”所在命令的参数提供。参见表格:https://tldp.org/LDP/abs/html/options.html
(感谢@jkh和@BMitch帮助我了解发生了什么。)