如何通过docker run将参数传递给Shell脚本

lo8azlld  于 2023-08-07  发布在  Shell
关注(0)|答案(8)|浏览(155)

我是Docker世界的新手。我必须调用一个shell脚本,该脚本通过docker容器获取命令行参数。例如:我的shell脚本看起来像:

#!bin/bash
echo $1

字符串
Dockerfile看起来像这样:

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh


我不确定如何在运行容器时传递参数

rkttyhzu

rkttyhzu1#

使用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

35g0bw71

35g0bw712#

使用相同的file.sh

#!/bin/bash
echo $1

字符串
使用现有的Dockerfile构建镜像:

docker build -t test .


使用参数abcxyz或其他参数运行图像。

docker run -ti --rm test /file.sh abc

docker run -ti --rm test /file.sh xyz

clj7thdc

clj7thdc3#

这里有几个相互作用的东西:

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


关于这一点有更多的细节:

  • https://docs.docker.com/engine/reference/run/#cmd-default-command-or-options
  • https://docs.docker.com/engine/reference/builder/#exec-form-entrypoint-example
7fhtutme

7fhtutme4#

在Docker中,传递这类信息的正确方式是通过环境变量。
因此,使用相同的Dockerfile,将脚本更改为

#!/bin/bash
echo $FOO

字符串
构建完成后,使用以下docker命令:

docker run -e FOO="hello world!" test

wmomyfyw

wmomyfyw5#

我所拥有的是一个实际运行的脚本文件。此脚本文件可能相对复杂。我们称之为“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脚本。
这是我的解决方案:
驳接文件:

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]

uurv41yg

uurv41yg6#

如果你想在编译时运行它:

CMD /bin/bash /file.sh arg1

字符串
如果你想在运行时运行它:

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]


然后在主机 shell 中

docker build -t test .
docker run -i -t test

mctunoxg

mctunoxg7#

我想使用字符串版本的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的回答帮助我理解了正在发生的事情。

ocebsuys

ocebsuys8#

另一个选择

让这一切成真

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

相关问题