Docker:在 Tomcat 镜像构建期间访问 MySQL 容器

Posted

技术标签:

【中文标题】Docker:在 Tomcat 镜像构建期间访问 MySQL 容器【英文标题】:Docker : accessing MySQL container during Tomcat image build 【发布时间】:2018-02-16 12:54:12 【问题描述】:

我正在尝试创建 Jahia CMS(数字体验管理器)的 Docker 安装。

我需要:

    一个 MySQL 容器 一个 Jahia 容器(嵌入式 Tomcat

诀窍在于,在 Jahia 容器构建(使用Expect 进行产品安装)期间,我需要访问 mysql 容器(需要进行连接检查)。

MySQL Dockerfile

FROM mysql:5.6

Jahia Dockefile

FROM centos:centos6

# Install dependencies
RUN yum -y update && yum -y install ...

# Download Digital Experience Manager 7.1.1
RUN wget -q https://www.jahia.com/downloads/jahia/digitalexperiencemanager7.1.1/DigitalExperienceManager-EnterpriseDistribution-7.1.1.0-r53717.3663.jar -O /tmp/DigitalExperienceManager.jar

# Download MySQL connector (only needed for standalone db installation)
RUN wget -q http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.44/mysql-connector-java-5.1.44.jar -O /usr/lib/mysql-connector-java-5.1.44.jar

# Launch installation using Expect to automate user input
COPY jahia_conf.exp /tmp/configuration.exp
RUN expect /tmp/configuration.exp

# Start Jahia
/opt/DigitalExperienceManager-EnterpriseDistribution-7.1.1.0/tomcat/bin/catalina.sh jpda run

期待脚本 (jahia_conf.exp)

#!/bin/sh
#!/usr/bin/expect

spawn java -jar /tmp/DigitalExperienceManager.jar -console

# Installation directory
expect "Select target path"
send "/opt/DigitalExperienceManager-EnterpriseDistribution-7.1.1.0\r"

# MySQL connector JAR file
expect "Specify the path to the downloaded driver JAR file"
send "/usr/lib/mysql-connector-java-5.1.44.jar\r"

# Database configuration
expect "Database URL (*)"
send "jdbc:mysql://mysql:3306/jahia?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=false\r"

当然,我在图像构建过程中会出错,因为它会在数据库 URL 输入后立即检查连接:

建立与数据库的连接时出错 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 通讯链路故障

最后一个成功发送到服务器的数据包是 0 毫秒 前。驱动没有收到来自服务器的任何数据包..

确实,我只是在构建 Jahia 映像,因此mysql 容器尚无法访问(即使正在运行)。

如何处理这种情况(在构建过程中需要访问另一个容器时)?

【问题讨论】:

在容器构建过程中你绝对需要访问mysql吗?您是否有理由不能将 expect /tmp/configuration.exp 和启动 Jahia 的最终命令放入在容器启动时运行的 entrypoint.sh 中? 如果我把它作为入口点,它会在我每次停止/启动容器时安装整个 CMS。 【参考方案1】:

由于 MySQL 服务器也将在一个容器中,我认为您不应该在构建时配置它,因为您不能假设数据库会启动。

不幸的是,我不知道“期望”工具是如何工作的,但理想情况下,您应该仅在容器启动时链接 Jahia 容器中的数据库。这可以通过配置注入来完成(环境变量或启动容器时可以注入的其他东西)

这意味着 MySQL 容器应该将数据库安装在一个单独的进程中。例如,在我们这边,我们通过直接在数据库上运行 jahia 代码中提供的 sql 脚本来做到这一点。

使用此解决方案,您可以确保在构建时不需要预安装数据库。

编辑:确实,Jahia 在构建时会对数据库进行一些检查,但您可以添加一个输入,这样 Jahia 就不需要对数据库执行操作。它使用 izpack 自动播放文件。这允许重播安装。

数据库设置部分如下:

<com.izforge.izpack.panels.UserInputPanel id="dbSettings">
<userInput>
<entry key="dbSettings.connection.url.mssql" value="jdbc:sqlserver://DB_SERVER;DatabaseName=DB_NAME;"/>
<entry key="dbSettings.dbms.createTables" value="false"/>
<entry key="dbSettings.connection.username" value="DB_USER"/>
<entry key="dbSettings.dbms.storeFilesInDB" value="false"/>
<entry key="dbSettings.connection.driver.mssql" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<entry key="dbSettings.connection.password" value="DB_PASSWORD"/>
</userInput>
</com.izforge.izpack.panels.UserInputPanel>

这假设不幸的是您在某处有一个数据库服务器。在我们这边,我们使用假实例,因为我们要求在构建期间不进行安装。

【讨论】:

但是 Jahia 安装要求数据库启动,否则它会失败。在构建时检查它不是我的选择,它是 Jahia 安装过程的要求。 (Expect 只是一个允许在安装过程中提示时自动发送用户输入的工具,它与问题没有直接关系,我可以在问题中忽略它。 我再次检查了我们的代码,你是对的,在构建期间有一个数据库检查。我们通过 jar 使用安装,提供一个 xml 文件作为参数(因此在我们的例子中我们不需要 Expect)。我将更新我的答案以提供 xml 部分。 其实 Expect 做的事情和 izpack 差不多。我可以使用假的 MySQL 实例进行安装,但我怀疑 Jah​​ia 也在那里进行了一些配置,因此在安装后简单地回来修改数据库设置以使用容器化的设置可能是有风险的。我将联系 Jahia 支持部门,了解他们对此的看法。【参考方案2】:

尝试使用docker commit。您可能必须运行 configuration.exp 脚本来通过执行到您的容器中来设置 Jahia。然后使用 docker commit 将对文件系统的更改保存到新映像中。该图像应保留初始配置。

请注意,卷不包含在 docker 提交中,因为它们位于 Docker 的联合文件系统之外。看起来您没有在 Dockerfile 中声明任何卷,因此这对您来说可能不是问题。 This answer 详细说明了 docker 提交和数据库卷,但前提是任何容器都相同。

【讨论】:

最后我只是使用了您评论中所述的解决方案,即在容器运行时执行 Jahia 安装。因此,我将一个 shell 脚本设置为入口点命令(docker compose),在其中我只需检查 Jahia 是否已安装,并仅在需要时启动安装。这样我就可以重建/重新启动我的图像/容器,而不必担心每次都提交。

以上是关于Docker:在 Tomcat 镜像构建期间访问 MySQL 容器的主要内容,如果未能解决你的问题,请参考以下文章

Docker容器-构建Tomcat业务镜像

构建Docker镜像实战

Docker Review - dockerfile 实战_使用dockerfile制作tomcat镜像

docker—部分镜像模板

docker—部分镜像模板

构建Docker镜像:tomcat