链接Docker图像并按顺序执行

时间:2015-08-20 18:28:19

标签: docker wildfly-8 dockerfile apiman

我正在使用我自己的图像扩展APIMan / Wildfly Docker镜像,这将做两件事:

  

1)将我的.war文件应用程序放入Wildfly   独立/部署目录

     

2)执行一系列查询Wildfly的cURL命令   服务器以配置APIMan。

最初,我尝试创建两个Docker镜像(第一个放入.war文件,第二个执行cURL命令),但我错误地认为最内层图像中的CMD指令将首先执行并且CMD&# 39; s将被向外执行。

例如:

ImageA:
FROM jboss/apiman-wildfly:1.1.6.Final
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
COPY /RatedRestfulServer/target/RatedRestfulServer-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/

CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c", "standalone-apiman.xml"]

ImageB:
FROM ImageA
COPY /configure.sh /opt/jboss/wildfly/

CMD ["/opt/jboss/wildfly/configure.sh"]

我最初假设在运行时期间首先启动Wildfly / APIMAN(根据ImageA CMD指令),然后运行我的自定义脚本(根据ImageB CMD指令)。我假设这是不正确的,因为在整个层次结构中,只执行了1条CMD指令(链中最外面的Dockerfile中的最后一条指令)?

所以,然后我尝试将所有内容合并到1个Dockerfile中,这将(在构建过程中)启动Wildfly / APIMAN,运行cURL命令,关闭wildfly服务器,然后CMD命令将在运行时和Wildfly期间重新启动它/ APIMan将被配置。但是,这不起作用,因为当我启动Wildfly(作为构建的一部分)时,它控制控制台并等待显示日志消息,因此构建永远不会完成。如果我追加'&'在RUN命令结束时,它不会运行(Dockerfile : RUN results in a No op)。

这是我尝试的Dockerfile:

FROM jboss/apiman-wildfly:1.1.6.Final
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
COPY /RatedRestfulServer/target/RatedRestfulServer-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/
COPY /configure.sh /opt/jboss/wildfly/
RUN /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 -c standalone-apiman.xml
RUN /opt/jboss/wildfly/configure.sh
RUN /opt/jboss/wildfly/bin/jboss-cli.sh --connect controller=127.0.0.1 command=:shutdown

CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c", "standalone-apiman.xml"]

这有什么解决方案吗?我试图让我的" configure.sh"在Wildfly / APIMan启动后运行脚本。在构建过程中或在运行时,这对我来说无关紧要,但是在构建过程中我没有看到任何方法,因为Wildfly没有守护进程模式

3 个答案:

答案 0 :(得分:1)

  

只执行1条CMD指令(链中最外面的Dockerfile中的最后一条指令)?

是的,这是正确的,请记住,CMD不是在构建时运行,而是在实例化时运行。实质上,当您从CMD

实例化容器时,您在第二个Dockerfile ImageB中正在执行的操作将覆盖第一个

如果您正在使用某种Rest API或cli或cURL连接到Wildfly服务器,我建议您在容器的实例化之后进行该配置,而不是在容器的构建之后。这样:

CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c", "standalone-apiman.xml"]`

总是你的最后一个命令。 如果您需要一些额外的文件或配置文件的更改,您可以将它们放在Dockerfile中,以便在实例化时调用CMD之前在构建时复制它们。

总结如下:

1)使用此Dockerfile(docker build)构建您的Docker容器:

FROM jboss/apiman-wildfly:1.1.6.Final
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
COPY /RatedRestfulServer/target/RatedRestfulServer-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/
COPY /configure.sh /opt/jboss/wildfly/
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c", "standalone-apiman.xml"]

2)运行(从新创建的图像中实例化容器)

docker run <image-id>

3)从容器或从Wildfly以相同方式配置的主机运行以下命令。假设您使用一些Rest API来配置(即使用cURL):

/opt/jboss/wildfly/configure.sh

您可以使用以下内容实例化第二个容器来运行此命令:

docker run -ti <image-id> /bin/bash

答案 1 :(得分:1)

构建一张图片:

FROM jboss/apiman-wildfly:1.1.6.Final
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
COPY /RatedRestfulServer/target/RatedRestfulServer-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/
COPY /configure.sh /opt/jboss/wildfly/
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c", "standalone-apiman.xml"]

启动它。启动完成后,使用docker exec命令在正在运行的容器中启动配置脚本。

docker run -d --name wildfly <image name>
docker exec wildfly /opt/jboss/wildfly/configure.sh

答案 2 :(得分:1)

我的问题背后的原始前提(尽管在原始帖子中没有明确说明)是在图像中配置APIMan并且没有图像之外的任何干预。

这有点像黑客,但我能够通过创建3个脚本来解决这个问题。一个用于启动Wildfly,一个用于运行配置脚本,另一个用于执行它们。希望这可以节省其他一些可怜的灵魂花一天时间来解决所有这些问题。

由于Dockerfile的性质仅允许在运行时进行1次执行调用,因此该调用需要是自定义脚本。

以下是带注释的文件。

<强> Dockerfile

FROM jboss/apiman-wildfly:1.1.6.Final
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
COPY /RatedRestfulServer/target/RatedRestfulServer-1.0-SNAPSHOT.war /opt/jboss/wildfly/standalone/deployments/
COPY /configure.sh /opt/jboss/wildfly/
COPY /execute.sh /opt/jboss/wildfly/
COPY /runWF.sh /opt/jboss/wildfly/

CMD ["/opt/jboss/wildfly/execute.sh"]

注意,图像中内置了所有3个脚本。 execute.sh脚本在运行时(实例化)而不是构建时执行。

<强> execute.sh

#!/bin/sh

/opt/jboss/wildfly/configure.sh &
/opt/jboss/wildfly/runWF.sh

请注意,configure.sh脚本将发送到后台,以便我们可以在configure.sh仍在运行时继续运行runWF.sh脚本。

<强> configure.sh

#!/bin/sh

done=""
while [ "$done" != "200" ]
do
        done=$(curl --write-out %{http_code} --silent --output /dev/null -u username:password -X GET -H "Accept: application/json" http://127.0.0.1:8080/apiman/system/status)
        sleep 3
done

# configuration curl commands
curl ...
curl ...

上面的configure.sh脚本在一个循环中运行,每隔3秒通过curl查询wildfly / apiman服务器,检查其状态。一旦它返回HTTP状态代码200(表示“启动并运行”状态),它就会退出循环并自由移动到配置。注意,通过提供另一种退出循环的方法(例如在一定数量的查询之后等),这应该可以使得“更安全”。我想这会给生产开发人员带来心悸,我不建议将其部署在生产中,但它暂时有效。

<强> runWF.sh

#!/bin/sh

/opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 -c standalone-apiman.xml

此脚本只是启动服务器。参数将各种模块绑定到0.0.0.0,并指示wildfly使用apiman独立xml文件进行配置。

在我的机器上,它需要wildfly + apiman(使用我的自定义war文件)大约10-15秒(取决于我运行它的计算机)才能完全加载,但是一旦它完成,配置脚本将能够成功查询,然后使用配置curl命令继续。同时,wildfly仍然控制着控制台,因为它是最后启动的,你可以监视活动并用ctrl-c终止进程。