在Docker镜像中传递Docker运行时环境变量

13
这是我的Docker镜像。我想覆盖下面设置的默认环境变量,使其从最后提到的docker运行命令中传递的内容中获取。

这是我的Docker镜像。我希望能够从最后提到的docker运行命令中覆写默认的环境变量设置。

FROM ubuntu:16.04

ADD http://www.nic.funet.fi/pub/mirrors/apache.org/tomcat/tomcat-8/v8.0.48/bin/apache-tomcat-8.0.48.tar.gz /usr/local/
RUN cd /usr/local && tar -zxvf apache-tomcat-8.0.48.tar.gz && rm apache-tomcat-8.0.48.tar.gz
RUN mv /usr/local/apache-tomcat-8.0.48 /usr/local/tomcat
RUN rm -rf /usr/local/tomcat/webapps/*

ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
ENV CATALINA_HOME /usr/local/tomcat
ENV CATALINA_BASE /usr/local/tomcat
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

ENV dummy_url defaulturl
ENV database databasedefault

COPY my.war /usr/local/tomcat/webapps/

RUN echo >> /usr/local/tomcat/conf/test.properties
RUN echo dummy_url =$dummy_url >> /usr/local/tomcat/conf/test.properties
RUN echo database =$database >> /usr/local/tomcat/conf/test.properties

ENTRYPOINT ["catalina.sh", "run"]
在本地运行:
docker run -p 8080:8080 -e dummy_url=http:google.com -e database=jdbc://mysql allimages/myimage:latest

在我添加它们的文件test.properties中,dummy_url和database似乎没有被覆盖。有任何想法将不胜感激。


我认为在覆盖环境变量之前,您应该将其写入文件。尝试进入容器 docker exec -it <container_name> 并运行 printenv - Bukharov Sergey
2
正如我在 https://dev59.com/S1gR5IYBdhLWcg3ww_3e#40873331?noredirect=1#comment83384105_40873331 中提到的那样,RUN 命令只在编译时执行(docker build)。您的属性文件已经设置好了。您需要让 ENTRYPOINT 调用一个脚本来执行您的 RUN 命令,并调用 catalina.sh。 - VonC
是的,我尝试使用docker exec命令来查看更改的属性,但它们仍然设置为默认值。我将尝试@VonC提到的方法。 - Righto
我会在今天晚些时候发布答案(我现在正在工作)。 - VonC
2个回答

7
我希望你能覆盖下面设置的默认环境变量,这些变量是从docker run命令中传递的。这意味着在运行镜像作为容器时(docker run),覆盖一个镜像文件(/usr/local/tomcat/conf/test.properties),而不是在构建镜像时(docker build及其--build-args选项ARG Dockerfile条目)。这意味着您需要在本地创建一个脚本文件:

即:

myscript.sh

#!/bin/sh
echo dummy_url=$dummy_url >> /usr/local/tomcat/conf/test.properties
echo database=$database >> /usr/local/tomcat/conf/test.properties
args=("$@")
catalina.sh run "${args[@]}"

你需要修改 {{link1:Dockerfile},将那个脚本复制并调用它:
COPY myscript.sh /usr/local/
...
ENTRYPOINT ["/usr/local/myscript.sh"]

然后,只有这样,docker run 的 -e 选项才会生效。

感谢@VonC。我昨天就实现了这个。我接受这个答案,因为它完全解决了问题并且清晰简明。 - Righto

3
您可能会混淆在构建镜像时执行什么以及启动容器时执行什么。 Dockerfile 中的 RUN 命令是在构建镜像时执行的,当运行 docker build... 时。
RUN echo dummy_url =$dummy_url >> /usr/local/tomcat/conf/test.properties
RUN echo database =$database >> /usr/local/tomcat/conf/test.properties

因此,当上述文件执行时,test.properties文件将包含Dockerfile中指定的默认值。
当您执行docker run -p 8080:8080 -e dummy_url=http:google.com -e database=jdbc://mysql allimages/myimage:latest时,ENTRYPOINT ["catalina.sh", "run"]将使用环境变量dummy_url=http:google.comdatabase=jdbc://mysql执行。
您可以使用以下方法允许在test.properties中覆盖值:
  1. $dummy_url >> /usr/local/tomcat/conf/test.properties$database >> /usr/local/tomcat/conf/test.properties移动到catalina.sh脚本的开头。

  1. 在构建镜像时覆盖这些值:

ARG dummy_url_arg
ARG database_arg

ENV dummy_url $dummy_url_arg
ENV database $database_arg

COPY my.war /usr/local/tomcat/webapps/

RUN echo >> /usr/local/tomcat/conf/test.properties
RUN echo dummy_url =$dummy_url >> /usr/local/tomcat/conf/test.properties
RUN echo database =$database >> /usr/local/tomcat/conf/test.properties

ENTRYPOINT ["catalina.sh", "run"]

构建镜像时,使用docker build --build-arg dummy_url_arg=http:google.com --build-arg database_arg=jdbc://mysql allimages/myimage:latest ...覆盖值。


谢谢!我该如何创建一个新的脚本,其中包含上面的移动命令,然后调用catalina.sh?入口点会是什么样子?我尝试使用您提到的构建命令来完成这个操作,但由于我将部署ECS任务并从那里传递这些参数,所以我想避免将其作为构建步骤。 - Righto
另外,如果我将所有这些属性设置在CATALINA_OPTS="-Ddummy_url=http://google.com -Ddatabase=somedb"下,而不是使用test.properties文件,我该如何确保这些属性被识别并更新test.properties文件。我更喜欢使用原始的catalina.sh文件,要么使用CATALINA_OPTS参数,要么使用一个单独的.sh文件来触发catalina.sh文件。 - Righto
创建一个新的脚本,包含以下内容 $dummy_url >> /usr/local/tomcat/conf/test.properties $database >> /usr/local/tomcat/conf/test.properties sh ./catalania.sh run 并将 ENTRYPOINT ["script.sh", "run"] 更改为其他内容。 - yamenk
我遇到了一个奇怪的错误 - standard_init_linux.go:185: exec user process caused "no such file or directory"。 我的.sh文件以#!/bin/bash开头,然后是所有echo property1=$property1 >> /usr/local/tomcat/test.properties语句,最后只需添加$CATALINA_HOME/bin/catalina.sh run。 - Righto
我也尝试在我编写的脚本顶部加入#!/bin/sh,但是仍然遇到了相同的错误。 - Righto
好的,在我按照这里关于上述错误的一些说明后,它成功了 - http://willi.am/blog/2016/08/11/docker-for-windows-dealing-with-windows-line-endings/ 感谢你的帮助! - Righto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接