如何在ENTRYPOINT数组中使用Docker环境变量?

Psy*_*nch 85 docker dockerfile

如果我设置一个环境变量,比方说ENV ADDRESSEE=world,我想在入口点脚本中使用它连接成一个固定的字符串,如:

ENTRYPOINT ["./greeting", "--message", "Hello, world!"]
Run Code Online (Sandbox Code Playgroud)

world作为环境varible的价值,我该怎么办呢?我试过使用,"Hello, $ADDRESSEE"但似乎没有用,因为它需要$ADDRESSEE字面意思.

vit*_*itr 168

你正在使用ENTRYPOINT 的exec形式.与shell表单不同,exec表单不会调用命令shell.这意味着不会发生正常的shell处理.例如,ENTRYPOINT [ "echo", "$HOME" ]不会对$ HOME进行变量替换.如果你想要shell处理,那么要么使用shell表单,要么直接执行shell,例如:ENTRYPOINT [ "sh", "-c", "echo $HOME" ].
当使用exec表单并直接执行shell时,就像shell表单的情况一样,它是执行环境变量扩展的shell,而不是docker.(来自Dockerfile引用)

在你的情况下,我会使用shell形式

ENTRYPOINT ./greeting --message "Hello, $ADDRESSEE\!"
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常有用的建议,我在我读过的任何教程中都没有看到过. (5认同)
  • 虽然它有效,但它似乎会产生一些新问题,例如不包含传递给该入口点的参数。例如,您不能将 `--attitude "shouting"` 参数添加到 `docker run` 命令中,该命令应传递给 `./greeting` (4认同)
  • 请注意,shell 形式可能会导致信号无法传递到进程(示例中为“greeting”)。https://hynek.me/articles/docker-signals/ (4认同)
  • 如果您还想通过docker run`调用将其他变量传递给`。/ greeting`(或传递`CMD`),请使用`ENTRYPOINT ./greeting --message“ Hello,$ ADDRESSEE \!$ 0 $ @”`。的Dockerfile) (3认同)
  • `ENTRYPOINT java -jar /dockertest.jar -Djava.security.egd = file:/ dev /./ urandom -Dserver.port = $ port`而`ENV port = 123`.端口ENV未解析.有什么想法吗? (2认同)

mlo*_*o55 16

在经历了很多痛苦以及@vitr 等人的大力帮助之后,我决定尝试

  • 标准 bash 替换
  • 外壳形式入口点(从上面极大尖端)

这奏效了。

ENV LISTEN_PORT=""

ENTRYPOINT java -cp "app:app/lib/*" hello.Application --server.port=${LISTEN_PORT:-80}
Run Code Online (Sandbox Code Playgroud)

例如

docker run --rm -p 8080:8080 -d --env LISTEN_PORT=8080 my-image
Run Code Online (Sandbox Code Playgroud)

docker run --rm -p 8080:80 -d my-image
Run Code Online (Sandbox Code Playgroud)

两者都在我的容器中正确设置了端口

参考资料

https://www.cyberciti.biz/tips/bash-shell-parameter-substitution-2.html


sma*_*c89 15

对我来说,我想将脚本的名称存储在变量中,并仍然使用 exec 形式。

注意:确保您尝试使用的变量已从命令行或通过指令声明为环境变量ENV

最初我做了类似的事情:

ENTRYPOINT [ "${BASE_FOLDER}/scripts/entrypoint.sh" ]
Run Code Online (Sandbox Code Playgroud)

但显然这不起作用,因为我们使用的是shell形式,并且列出的第一个程序需要是PATH. 所以为了解决这个问题,这就是我最终要做的:

ENTRYPOINT [ "/bin/bash", "-c", "exec ${BASE_FOLDER}/scripts/entrypoint.sh \"${@}\"", "--" ]
Run Code Online (Sandbox Code Playgroud)

注意需要双引号

这样做的目的是允许我们获取传递给 的任何额外参数/bin/bash,并在 bash 解析名称后将这些相同的参数提供给我们的脚本。


男人 7 狂欢

--
A -- 表示选项结束并禁用进一步的选项处理。-- 之后的任何参数都被视为文件名和参数。- 的参数相当于 --。

PS--还可以与任何兼容 POSIX 的 shell 配合使用。请参阅实用程序语法指南

  • 这很好用。如果没有 `"--"` bash 将窃取第一个参数并且永远不会将其提供给脚本,并且 `"--"` 会使事情按预期工作。不过,有两个改进。1) 该命令应以 `exec` 开头:`"exec ${BASE_FOLDER}/..."`。否则脚本/可执行文件将无法正确接收信号。2) 为了正确处理传递给 CMD 的带引号的参数,它应该是 `\"${@}\"` 而不仅仅是 `${@}`。 (5认同)
  • @smac98根据 [ENTRYPOINT docs](https://docs.docker.com/engine/reference/builder/#entrypoint),如果 shell 是父进程,则当 `docker stop 时,它不会将 `SIGTERM` 传播到您的脚本。 ..` 已运行。您可以搜索有关“docker pid 1 signal”的更多信息,或者在[Google的最佳实践](https://cloud.google.com/architecture/best-practices-for-building-containers)中阅读有关它的信息?hl=tr#solution_1_run_as_pid_1_and_register_signal_handlers)。另外,还请注意,“ENTRYPOINT”数组元素不允许使用单引号,它们需要用双引号引起来。 (4认同)
  • 您描述的情况是当“bash”从“ENTRYPOINT”开始执行到另一个运行您的脚本的“bash”时。如果我们假设 bash 在正确处理信号方面存在问题,则不应将其用作测试的实际进程。其次,我不确定你使用的是什么平台,通常 Ctrl-Z 发送“SIGTSTP”,而不是“SIGSTOP”。为了真正测试发生的情况,您需要引发运行“docker stop”时生成的“SIGTERM”信号。 (2认同)

Tal*_*ues 14

我很简单地解决了这个问题!

重要提示:您希望在 中使用的变量ENTRYPOINT 必须ENV类型(而不是ARG类型)。

示例#1:

ARG APP_NAME=app.jar                    # $APP_NAME can be ARG or ENV type.
ENV APP_PATH=app-directory/$APP_NAME    # $APP_PATH must be ENV type.
ENTRYPOINT java -jar $APP_PATH
Run Code Online (Sandbox Code Playgroud)

执行以下命令将导致: java -jar app-directory/app.jar

示例#2(您的问题):

ARG ADDRESSEE="world"                       # $ADDRESSEE can be ARG or ENV type.
ENV MESSAGE="Hello, $ADDRESSEE!"            # $MESSAGE must be ENV type.
ENTRYPOINT ./greeting --message $MESSAGE
Run Code Online (Sandbox Code Playgroud)

执行以下命令将导致: ./greeting --message Hello, world!

  • 请确认分配字符串变量时是否需要引号。 ""

我的提示:只要有可能,就使用ENV而不是ARG避免你或一方的混乱SHELL

  • 为了以防万一,可以自定义 ENV:`ARG TEST; ENV TEST =“$ {TEST:-foo}”`。相关:https://docs.docker.com/compose/environment-variables/#substitute-environment-variables-in-compose-files https://www.gnu.org/software/bash/manual/html_node/Shell-参数扩展.html (2认同)

Ben*_*man 9

我尝试解决建议的答案,但仍然遇到了一些问题...

这是解决我的问题的方法:

ARG APP_EXE="AppName.exe"
ENV _EXE=${APP_EXE}

# Build a shell script because the ENTRYPOINT command doesn't like using ENV
RUN echo "#!/bin/bash \n mono ${_EXE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh

# Run the generated shell script.
ENTRYPOINT ["./entrypoint.sh"]

具体针对您的问题:
RUN echo "#!/bin/bash \n ./greeting --message ${ADDRESSEE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

  • 我很想听听你的做法,然后@ReverendTim ;) (8认同)