在EC2上的Docker,在dockerfile中的RUN命令没有读取环境变量

时间:2016-11-04 16:38:42

标签: amazon-web-services docker elastic-beanstalk

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

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

当然每个环境都使用docker容器来托管glassfish实例,所以我首先想到的是为elastic-beanstalk配置一个环境变量。在这种情况下

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命令在容器完全加载之前运行的东西,可能缺少弹性beanstalk注入的变量。所以我尝试将代码移动到ENTRYPOINT指令。没有运气,容器启动失败。还试过

ENTRYPOINT ["command", "param"]

语法,但它没有给出

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

因此,我被困住了。

2 个答案:

答案 0 :(得分:2)

你需要:

1 / 使用入口点(或至少使用sh -c 'if...'语法):用于运行时执行,而不是编译时图像构建。

2 /使用build-time variables (--build-arg)

  

您可以在Dockerfile中使用ENV指令来定义变量值。这些值在构建的图像中持续存在   但是,持久性往往不是你想要的。用户希望根据他们在哪个主机上构建图像来指定不同的变量。

     

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

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

在您的情况下,您的Dockefile应包括:

ENV ypenvironment

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

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

  

我需要能够在dev和pro环境中使用相同的EAR包,

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

您的Dockerfile仍需要包含:

ENV ypenvironment

但是你需要用

运行你的一个图像
docker run -x ypenvironment=dev ...

确保您的脚本(由您的入口点引用)包含您在问题中提到的if [ "$ypenvironment"="pro" ] ; then...以及您应用的实际启动(在前景中)。 您的脚本需要立即退出 not ,否则您的容器会在启动后立即切换到退出状态。

答案 1 :(得分:2)

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

CMDENTRYPOINT命令是特殊的构建时命令,它告诉Docker从该映像部署容器时要执行的命令。

现在,在您的情况下,更好的方法是检查Glassfish是否支持domain.xml(或其他地方)内的环境变量。如果是,则可以对两个环境使用相同的domain.xml文件,并为这两个环境使用相同的Docker镜像。然后,通过在本地运行时使用docker run -e "VAR=value"运行时环境变量注入容器,然后使用环境属性配置部分来区分环境。在Elastic Beanstalk上部署。

编辑:如果您无法在domain.xml内使用环境变量,可以通过使用脚本启动容器来解决问题,该脚本读取运行时环境变量并放置其值使用domain.xmlsed中的正确位置,然后像往常一样启动应用程序。您可以在this post中找到一个示例。