我是docker世界的新手。我需要通过一个docker容器调用一个带有命令行参数的shell脚本。 例如:我的shell脚本如下:
#!bin/bash
echo $1
Dockerfile 的样子是这样的:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定如何在运行容器时传递参数
我是docker世界的新手。我需要通过一个docker容器调用一个带有命令行参数的shell脚本。 例如:我的shell脚本如下:
#!bin/bash
echo $1
Dockerfile 的样子是这样的:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定如何在运行容器时传递参数
使用这个脚本 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
docker build -t test .
使用参数abc
、xyz
或其他内容运行该图像。
docker run -ti --rm test /file.sh abc
docker run -ti --rm test /file.sh xyz
docker run -ti test /file.sh abc
。我感觉脚本不会运行,因为应该是 docker run -ti test sh /file.sh abc
。sh或/bin/sh才能正确运行它。 - Vamsidhar Muggulladocker run your_image arg1 arg2
会用arg1 arg2
替换CMD
的值。这是对CMD的完全替换,而不是追加更多的值。这就是为什么你经常看到docker run some_image /bin/bash
在容器中运行bash shell。
当你同时定义了ENTRYPOINT和CMD的值时,Docker会将两者连接起来并运行这个连接后的命令。所以如果你将entrypoint定义为file.sh
,现在你可以通过附加参数来运行容器,这些参数将作为参数传递给file.sh
。
Docker中的Entrypoints和Commands有两种语法,一种是字符串语法,它将启动一个shell,另一种是json语法,它将执行一个exec。Shell对于处理IO重定向、将多个命令链接在一起(使用&&
等)以及变量替换等非常有用。然而,这个shell会妨碍信号处理(如果你曾经看到停止容器需要10秒的延迟,通常就是这个原因)以及连接entrypoint和command在一起。如果你将entrypoint定义为一个字符串,它将运行/bin/sh -c "file.sh"
,这本身没问题。但是如果你也将command定义为一个字符串,你会看到类似/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"
的命令在容器内部被启动,这不太好。请参考这里的表格以了解更多关于这两个选项如何相互作用的信息。
shell的-c
选项只接受一个参数。之后的所有内容都将作为$1
、$2
等传递给这个单一的参数,但不会传递给嵌入的shell脚本,除非你显式地传递这些参数。例如,/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
["bash", "--login", "-c"]
,以获取镜像中的/etc/profile源文件,但后来我想知道为什么传递给docker run的shell脚本不会传递任何参数...你的答案解决了我的疑惑,谢谢! - ApteryxENTRYPOINT ["/file.sh"]
吗?即前面要加上 /
吗? - Dave#!/bin/bash
echo $FOO
构建完成后,请使用以下 Docker 命令:
docker run -e FOO="hello world!" test
pytest -m“not longest”
这是唯一对我有效的解决方案。无论是否“正确”,我很高兴它能用在这里。 - mildewey我手头有一个可以真正运行代码的脚本文件。这个脚本文件可能相对较为复杂,我们称之为“run_container”。这个脚本从命令行中获取参数:
run_container p1 p2 p3
一个简单的 run_container 可能是:
#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"
我想做的是,在“装配”后,我希望能够通过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 \"$@\"", "--"]
ENTRYPOINT
数组中的第三个值替换为 "/run_container \"$@\""
可以正确处理包含空格的参数(例如,docker run image_name foo 'bar baz' quux
)。 - davidchambers如果您想在构建时运行它:
CMD /bin/bash /file.sh arg1
如果你想在运行时运行它:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
然后在主机 shell 中执行
docker build -t test .
docker run -i -t test
ENTRYPOINT
对于我认为想要运行时的 OP 来说是一个很好的答案,但如果你真的想要构建时变量,那么这个答案就是错误的。请使用 ARG
和 docker build --build-arg
https://docs.docker.com/engine/reference/builder/#arg - Grae Kindel我想使用 ENTRYPOINT 的字符串版本,这样我就可以使用交互式 shell。
FROM docker.io/ubuntu
...
ENTRYPOINT python -m server "$@"
然后运行的命令(注意--
):
docker run -it server -- --my_server_flag
ENTRYPOINT
的字符串版本运行一个 shell,该 shell 使用 -c
标志指定的命令运行。在 --
之后传递给 shell 的参数将作为命令的参数提供,其中 "$@"
位于该命令中。请参见此处的表格:https://tldp.org/LDP/abs/html/options.html。(感谢 @jkh 和 @BMitch 的答案帮助我理解发生了什么。)另一个选项...
使其工作的方法是
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 ./file.sh
。 - phil294chmod +x file.sh
命令,以设置文件的可执行标记。 - topskip["/file.sh"]
、/file.sh
甚至[/file.sh]
之间有什么区别? - Nitzan