如何通过 docker 运行 将参数传递给 Shell 脚本
How to pass arguments to Shell Script through docker run
我是 docker 世界的新手。我必须调用一个 shell 脚本,该脚本通过 docker 容器获取命令行参数。
例如:我的 shell 脚本如下所示:
#!bin/bash
echo
Dockerfile 看起来像这样:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定如何在 运行 容器
时传递参数
如果你想运行它@构建时间:
CMD /bin/bash /file.sh arg1
如果你想运行它@运行时间:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
然后在宿主中shell
docker build -t test .
docker run -i -t test
使用相同的file.sh
#!/bin/bash
echo
使用现有的 Dockerfile 构建镜像:
docker build -t test .
运行 带有参数 abc
或 xyz
或其他参数的图像。
docker run -ti --rm test /file.sh abc
docker run -ti --rm test /file.sh xyz
对于Docker,传递此类信息的正确方法是通过环境变量。
因此,对于相同的 Docker 文件,将脚本更改为
#!/bin/bash
echo $FOO
构建后,使用以下docker命令:
docker run -e FOO="hello world!" test
我有一个脚本文件,实际上是 运行s 东西。这个脚本文件可能相对复杂。我们称它为 "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 作为参数。
这是我的解决方案:
Docker 文件:
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
会将 CMD
的值替换为 arg1 arg2
。这是 CMD 的完全替代,而不是向其附加更多值。这就是为什么你经常在容器中看到docker run some_image /bin/bash
到运行一个bashshell
当您同时定义了 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"
这样的东西作为在你的容器内启动的命令,不太好。参见 the table here for more on how these two options interact
shell-c
选项只接受一个参数。此后的所有内容都将作为 </code>、<code>
等传递给该单个参数,但不会传递给嵌入式 shell 脚本,除非您明确传递了参数。 IE。 /bin/sh -c "file.sh " "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
在以下位置有更多详细信息:
另一种选择...
为了使它有效
docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"
在 dockerfile
ENTRYPOINT ["/entrypoint.sh"]
在entrypoint.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
我是 docker 世界的新手。我必须调用一个 shell 脚本,该脚本通过 docker 容器获取命令行参数。 例如:我的 shell 脚本如下所示:
#!bin/bash
echo
Dockerfile 看起来像这样:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
我不确定如何在 运行 容器
时传递参数如果你想运行它@构建时间:
CMD /bin/bash /file.sh arg1
如果你想运行它@运行时间:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
然后在宿主中shell
docker build -t test .
docker run -i -t test
使用相同的file.sh
#!/bin/bash
echo
使用现有的 Dockerfile 构建镜像:
docker build -t test .
运行 带有参数 abc
或 xyz
或其他参数的图像。
docker run -ti --rm test /file.sh abc
docker run -ti --rm test /file.sh xyz
对于Docker,传递此类信息的正确方法是通过环境变量。
因此,对于相同的 Docker 文件,将脚本更改为
#!/bin/bash
echo $FOO
构建后,使用以下docker命令:
docker run -e FOO="hello world!" test
我有一个脚本文件,实际上是 运行s 东西。这个脚本文件可能相对复杂。我们称它为 "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 作为参数。
这是我的解决方案:
Docker 文件:
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
会将CMD
的值替换为arg1 arg2
。这是 CMD 的完全替代,而不是向其附加更多值。这就是为什么你经常在容器中看到docker run some_image /bin/bash
到运行一个bashshell当您同时定义了 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"
这样的东西作为在你的容器内启动的命令,不太好。参见 the table here for more on how these two options interactshell
-c
选项只接受一个参数。此后的所有内容都将作为</code>、<code>
等传递给该单个参数,但不会传递给嵌入式 shell 脚本,除非您明确传递了参数。 IE。/bin/sh -c "file.sh " "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
在以下位置有更多详细信息:
另一种选择...
为了使它有效
docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"
在 dockerfile
ENTRYPOINT ["/entrypoint.sh"]
在entrypoint.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