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

ENTRYPOINT ["./greeting", "--message", "Hello, world!"]

world是环境变量的值,我该怎么做呢?我尝试使用“你好,$ADDRESSEE”,但这似乎不工作,因为它需要$ADDRESSEE字面上。


当前回答

如果有人想要传递一个ARG或ENV变量到ENTRYPOINT的exec形式,那么可能会使用在映像构建过程中创建的临时文件。

在我的情况下,我必须启动不同的应用程序,这取决于。net应用程序是否已发布为自包含的。 我所做的是创建临时文件,并在bash脚本的if语句中使用它的名称。

dockerfile的一部分:

ARG SELF_CONTAINED=true #ENV SELF_CONTAINED=true also works
# File has to be used as a variable as it's impossible to pass variable do ENTRYPOINT using Exec form. File name allows to check whether app is self-contained
RUN touch ${SELF_CONTAINED}.txt
COPY run-dotnet-app.sh .
ENTRYPOINT ["./run-dotnet-app.sh", "MyApp" ]

run-dotnet-app.sh:

#!/bin/sh

FILENAME=$1

if [ -f "true.txt" ]; then
   ./"${FILENAME}"
else
   dotnet "${FILENAME}".dll
fi

其他回答

You're using the exec form of ENTRYPOINT. Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example, ENTRYPOINT [ "echo", "$HOME" ] will not do variable substitution on $HOME. If you want shell processing then either use the shell form or execute a shell directly, for example: ENTRYPOINT [ "sh", "-c", "echo $HOME" ]. When using the exec form and executing a shell directly, as in the case for the shell form, it is the shell that is doing the environment variable expansion, not docker.(from Dockerfile reference)

在你的例子中,我会用壳层形式

ENTRYPOINT ./greeting --message "Hello, $ADDRESSEE\!"

我试图用建议的答案来解决问题,但仍然遇到了一些问题……

这是我问题的解决方案:

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"]

如果有人想要传递一个ARG或ENV变量到ENTRYPOINT的exec形式,那么可能会使用在映像构建过程中创建的临时文件。

在我的情况下,我必须启动不同的应用程序,这取决于。net应用程序是否已发布为自包含的。 我所做的是创建临时文件,并在bash脚本的if语句中使用它的名称。

dockerfile的一部分:

ARG SELF_CONTAINED=true #ENV SELF_CONTAINED=true also works
# File has to be used as a variable as it's impossible to pass variable do ENTRYPOINT using Exec form. File name allows to check whether app is self-contained
RUN touch ${SELF_CONTAINED}.txt
COPY run-dotnet-app.sh .
ENTRYPOINT ["./run-dotnet-app.sh", "MyApp" ]

run-dotnet-app.sh:

#!/bin/sh

FILENAME=$1

if [ -f "true.txt" ]; then
   ./"${FILENAME}"
else
   dotnet "${FILENAME}".dll
fi

我使用上面“创建自定义脚本”方法的变体解决了这个问题。是这样的:

FROM hairyhenderson/figlet
ENV GREETING="Hello"
RUN printf '#!/bin/sh\nfiglet -W \${GREETING} \$@\n' > /runme && chmod +x /runme
ENTRYPOINT ["/runme"]
CMD ["World"]

docker container run -it --rm -e GREETING="G'Day" dockerfornovices/figlet-greeter Alec

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

标准bash替换 ENTRYPOINT的外壳形式(上面的伟大提示)

这很有效。

ENV LISTEN_PORT=""

ENTRYPOINT java -cp "app:app/lib/*" hello.Application --server.port=${LISTEN_PORT:-80}

如。

docker run --rm -p 8080:8080 -d --env LISTEN_PORT=8080 my-image

and

docker run --rm -p 8080:80 -d my-image

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

Refs

见https://www.cyberciti.biz/tips/bash -壳参数替换- 2. - html