2016-11-04 226 views
2

我在AWS上有两个弹性beanstalk环境:开发和生产。我在每个实例上运行一个glassfish服务器,并且要求相同的应用程序包可以在生产环境和开发环境中部署,而不需要两个不同的文件。这两个实例大小不同:dev有一个微型实例,而生产有一个中等的实例,因此我需要为glassfish部署两个不同的配置文件,每个环境一个。EC2上的Docker,dockerfile中的RUN命令没有读取环境变量

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

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

ypenvironment = dev 

的开发环境和

ypenvironment = pro 

用于生产环境。然后在我的DOCKERFILE我把这种说法在运行命令:

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

你需要:

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)


我需要能够使用相同的EAR包用于开发和亲环境,

然后,你希望你的入口点,运行的时候,要根据环境的价值移动文件变量。

你Dockerfile仍然需要包括:

ENV ypenvironment

但你需要与

docker run -x ypenvironment=dev ... 

运行一个像确保您的脚本(通过您的入口点引用)包括if [ "$ypenvironment"="pro" ] ; then...你在你的问题中提到,加上你的应用的实际启动(在前台)。
您的脚本需要而不是立即退出,或者您的容器在启动后立即切换到退出状态。

+0

对不起,它不清楚,但两个不同的构建是我想要避免的。我需要能够为dev和pro环境使用相同的EAR包,但在elastic-beanstalk中,您只能部署EAR文件,而EAR文件又必须包含DOCKERFILE。也许有一种方法可以在运行docker build命令的上下文中获取环境变量值,但我不知道。我会尽快编辑我的问题,谢谢! – Gabber

+0

@Gabber所以你说的是运行时,而不是构建时间(Dockerfile)? – VonC

+0

@Gabber我编辑了我的答案,包括运行时语法 – VonC

2

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

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

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

编辑:如果你不能使用内部domain.xml环境变量,您可以通过启动一个脚本读取运行环境变量,并把它们的值在正确的地方使用seddomain.xml容器解决问题,然后照常开始你的申请。你可以在this post找到一个例子。

+0

这不是我所要求的,而是我所需要的。感谢:) – Gabber

+0

对不起,我试过这个解决方案,但没有工作,恐怕不可能让Glassfish的domain.xml文件从aws环境读取变量,因此不能接受这个正确的答案 – Gabber

+0

然后,还有另一种解决方案恰好适用于这些情况。我已经更新了我的答案。祝你好运:-) –

相关问题