在EC2上的Docker,dockerfile中的RUN命令不能读取环境variables

我在AWS上有两个弹性beanstalk环境:开发和生产。 我在每个实例上运行一个glassfish服务器,并且要求在生产和开发环境中可以部署相同的应用程序包,而不需要两个不同的.EAR文件。这两个实例大小不同:dev有一个微型实例生产有一个中等的实例,因此我需要为glassfish部署两个不同的configuration文件,每个环境一个。

主要的问题是该文件必须在服务器启动之前在glassfish config目录中,因此我认为在创build容器时可以更好地移动它。

当然,每个环境都使用docker容器来托pipeglassfish实例,所以我首先想到的是为elastic-beanstalkconfiguration一个环境variables。 在这种情况下

 ypenvironment = dev 

为开发环境和

 ypenvironment = pro 

为生产环境。 然后在我的DOCKERFILE中,我把这个语句放在RUN命令中:

  RUN if [ "$ypenvironment"="pro" ] ; then \ mv --force /var/app/GF_domain.xml /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \ elif [ "$ypenvironment"="dev" ] ; then \ mv --force /var/app/GF_domain.xml.dev /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \ fi 

不幸的是,当启动完成后,两个GF_domain文件仍然在var/app

然后我发现RUN命令在容器满载之前运行了一些东西,可能缺less弹性beanstalk注入的variables。 所以我试图将代码移动到ENTRYPOINT指令。 再次运气,容器启动失败。 也试过了

 ENTRYPOINT ["command", "param"] 

语法,但它没有工作给一个

 System error: exec: "if": executable file not found in $PATH 

所以我卡住了。

你需要:

1 / 使用入口点(或者至less使用sh -c 'if...'语法):这是为了运行时执行,而不是编译时的图像构build。

2 /使用生成时间variables( --build-arg ) :

您可以在Dockerfile中使用ENV指令来定义variables值。 这些值坚持在build成的形象。
但是,往往坚持不是你想要的。 用户想要根据他们在哪个主机上构build图像来指定不同的variables。

一个很好的例子是用于拉取中间文件的http_proxy或源代码版本。 ARG指令允许Dockerfile作者定义用户可以在构build时使用--build-arg标志设置的值:

 $ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 . 

在你的情况下,你的Dockefile应该包括:

 ENV ypenvironment 

然后docker build --build-arg ypenvironment=dev ... myDevImage

您将构build2个不同的图像(基于相同的Dockerfile)


我需要能够为开发和专业环境使用相同的EAR包,

然后,在运行时,您希望您的ENTRYPOINT根据环境variables的值移动文件。

您的Dockerfile仍然需要包含:

ENV ypenvironment

但是你需要运行你的一个图像

 docker run -x ypenvironment=dev ... 

确保您的脚本(由您的入口点引用)包含if [ "$ypenvironment"="pro" ] ; then... if [ "$ypenvironment"="pro" ] ; then...你提到你的问题,加上你的应用程序的实际启动(在前台)。
您的脚本不需要立即退出,或者您的容器在启动后立即切换到退出状态。

在使用Docker时,您必须区分构build时操作和运行时操作。 Dockerfiles用于构buildDocker镜像 ,而不是用于部署容器。 这意味着Dockerfile中的所有命令在构buildDocker镜像时执行, 而不是在从中部署容器时执行。

CMDENTRYPOINT命令是特殊的构build时间命令,它告诉Docker在从映像部署容器时要执行什么命令。

现在,在你的情况下,更好的方法是检查GlassFish是否支持domain.xml (或其他地方)中的环境variables。 如果是这样,您可以在两种环境中使用相同的domain.xml文件,并为它们使用相同的Docker映像。 然后,通过在本地运行时使用docker run -e "VAR=value"注入运行时环境variables到容器,并在Elastic Beanstalk上部署时使用Environment Propertiesconfiguration部分,来区分这些环境。

编辑:如果你不能在domain.xml使用环境variables,你可以通过启动一个脚本来启动容器来解决问题,该脚本读取运行时环境variables,并使用sed将它们的值放在domain.xml中的正确位置,然后照常开始你的申请。 你可以在这篇文章中find一个例子。