使用 Flyway 和 Docker 容器内的嵌入式 Postgresql 运行测试时出现 java.net.ConnectException

Posted

技术标签:

【中文标题】使用 Flyway 和 Docker 容器内的嵌入式 Postgresql 运行测试时出现 java.net.ConnectException【英文标题】:java.net.ConnectException when running test with Flyway and embedded Postgresql inside Docker container 【发布时间】:2017-01-13 05:33:52 【问题描述】:

为了正确测试我的 Spring Boot 应用程序,我在集成测试中使用了 embedded Postgresql。此外,我也使用 Flyway,它被配置为使用基于 Postgresql 配置的数据源(查看 EmbeddedPostgresConfigurationFlywayConfiguration 类)。

在我的环境 (OS X) 上运行时,我的所有测试都顺利通过,但在 Docker 容器中运行时它们都失败了(java:8openjdk:8 图像)。而且我不知道造成这种差异的原因是什么以及如何修复它以使测试在 Docker 内部通过(进一步的持续集成管道需要它)。

这里是复制问题的最小代码示例:https://github.com/nkoder/postgresql-embedded-example。

要运行测试没有问题运行./gradlew clean test。要运行失败的测试,请运行 docker build .

在 Docker 内部运行测试期间抛出的错误:

java.lang.IllegalStateException
    Caused by: org.springframework.beans.factory.BeanCreationException
        Caused by: org.springframework.beans.BeanInstantiationException
            Caused by: org.flywaydb.core.api.FlywayException
                Caused by: org.postgresql.util.PSQLException
                    Caused by: java.net.ConnectException

我试图为自己解决这个问题,但我仍然只有一些猜测,没有什么可靠的。唯一的“提示”:对于嵌入式 Postgresql 配置中使用的硬编码(非随机)端口,有时在FlywayConfiguration 类中的flyway.clean(); 行中会发生类似的异常(当在实际项目中运行来自 IntelliJ IDEA 的测试并进行更多测试时),这似乎是通过提供的数据源访问数据库的第一行代码。

更新 1: Postgresql 实例是在随机开放端口 inside 同一 Docker 容器上的 localhost 测试期间创建的。我怀疑不需要连接到主机(外部容器)。

【问题讨论】:

ConnectException 总是在代理或防火墙阻止输出连接时出现。你看过 Docker 的互联配置吗? 测试和嵌入式 Postgresql 在同一个容器中运行。我的意思是在测试中有在localhost:<randomOpenPort> 创建的postgresql,它被用作数据源。容器“外部”没有任何东西可以到达互联网(或者至少我不知道)。 我明白了,但我坚持:即使通信保持在同一个本地主机内,连接到本地端口也可能被本地防火墙阻止。 好的,我当时误解了你,现在我明白了。会检查 【参考方案1】:

问题解决了!

根据https://github.com/yandex-qatools/postgresql-embedded,我们不能使用 root 在测试中运行嵌入式 Postgresql。因此,我需要解决的问题是以非 root 用户身份在 Docker 中运行测试。

您可以在此处查看修复:https://github.com/nkoder/postgresql-embedded-example/commit/391977052b1563cdcabf66a2fe3ca0a3e0a7b358

【讨论】:

【参考方案2】:

您的问题很可能是您的应用程序试图访问本地主机上的数据库。但是当它在 docker 容器中运行时,localhost 是容器而不是 hist 机器。因此,您必须更改配置才能使其正常工作。

【讨论】:

我想连接到 Docker 的本地主机(容器内)。主机上没有我想连接的东西。没有“外部”Postgresql,只有在测试运行期间在同一个容器内创建的这个。 如何创建 Postgres?如果您的容器中没有运行数据库,这就是它失败的原因。 Embedded Postgres 配置在EmbeddedPostgresConfiguration 中定义。没有独立的 Postgres(在 Docker 和我的测试通过的本地环境中都没有_ 嗯,但这就是我的意思。嵌入式 Postgres 不像 HSQL 或 H2 那样在 JVM DB 中,而只是一个启动本地实例的包装器,因为我了解 yandex 站点。因此,如果您的容器中没有安装 Postgres,它将无法正常工作。

以上是关于使用 Flyway 和 Docker 容器内的嵌入式 Postgresql 运行测试时出现 java.net.ConnectException的主要内容,如果未能解决你的问题,请参考以下文章

将 Flyway 添加到 MySQL Docker 容器

无法将docker Spring-Boot应用程序与docker-compose中的mysql容器和flyway连接起来

在 docker 容器上运行数据库时,Flyway 找不到迁移

无法在 docker 容器中加载 libjli.so

flyway 无法连接到 docker-entrypoint-initdb.d 脚本中的 postgres 容器

Flyway 无法从 Docker-Container 连接到 MySQL