2

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

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

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

最初,我尝试创建两个 Docker 映像(第一个放入 .war 文件,第二个执行 cURL 命令),但是我错误地认为最里面的映像中的 CMD 指令将首先执行,而 CMD 将向外执行.

例如:

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 导致 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"]

有什么解决办法吗?我正在尝试在 Wildfly / APIMan 启动后运行我的“configure.sh”脚本。这对我来说是在构建过程中还是在运行时完成并不重要,但是在构建过程中我看不到任何方法,因为 Wildfly 没有守护程序模式。

4

3 回答 3

2

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

是的,这是正确的,请记住,CMD 不是在构建时运行,而是在实例化时运行。本质上,您在第二个 Dockerfile 中所做的CMD是在您从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在实例化时调用它们。

总而言之:

Dockerfile1)用这个(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
于 2015-08-20T19:35:32.020 回答
2

我的问题背后的原始前提(尽管在原始帖子中没有明确说明)是在图像中配置 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 脚本在运行时(实例化)而不是构建时执行。

执行.sh

#!/bin/sh

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

注意,configure.sh 脚本被发送到后台,以便我们可以在 configure.sh 仍在运行时继续运行 runWF.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 服务器,检查其状态。一旦它返回 200 的 HTTP 状态代码(表示“启动并运行”状态),它就会退出循环并自由地进入配置。注意,通过提供另一种退出循环的方式(例如在一定数量的查询等之后),这可能会变得更“安全”。我想这会让生产开发人员心悸,我不建议在生产中部署它,但它暂时有效。

运行WF.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 终止进程。

于 2015-08-21T05:56:21.877 回答
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
于 2015-08-21T01:35:10.923 回答