使用 org.testcontainers 时如何在 docker 容器中包含 postgresql.conf
Posted
技术标签:
【中文标题】使用 org.testcontainers 时如何在 docker 容器中包含 postgresql.conf【英文标题】:How do you include postgresql.conf on docker container when using org.testcontainers 【发布时间】:2019-07-12 23:48:42 【问题描述】:是否可以通过配置给 postgresql 测试容器一个自定义的 postgresql.conf 文件?
我已经包含了maven依赖
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.10.6</version>
</dependency>
并为 DB url 使用“通过 JDBC URL 方案启动的数据库容器” 因此,我的 Spring Boot 应用程序中的设置为:
datasource:
url: jdbc:tc:postgresql:10-alpine:///databasename
driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
我需要在 postgresql.conf 中进行自定义设置。 有没有办法将 postgresql.conf 推送到由 testcontainers 启动的 docker 容器?
编辑 1
感谢@vilkg,不过我确实知道 TC_INITSCRIPT 脚本选项和 SET 函数:
我想要一个自定义设置,例如 my.key ALTER 系统不适用于您自己的设置,例如:ALTER SYSTEM SET my.key = 'jehe';获取错误 无法执行 SQL 命令。 返回消息:`错误:无法识别的配置参数“my.key” 我之前尝试过如下 SET 和 ALTER DATABASESET my.key = 'new value 8'; -- sets for current session
ALTER DATABASE test SET my.key = 'new value 8'; -- sets for subsequent sessions
select current_setting('my.key');
问题是
当 testcontainer 启动 postgres 容器时,我将它传递给一个初始化脚本以运行url: jdbc:tc:postgresql:10-alpine:///databasename?TC_INITSCRIPT=init_pg.sql
我可以包含上面的 SQL 很高兴..
我知道该 secret.key 的设置在此脚本中工作正常,因为它会在 select current_setting('my.key'); 行失败。如果其他两个被注释掉了
我也知道对 db name test 运行它是正确的,例如:'ALTER DATABASE test' 因为如果我使用不同的名称,它会失败
Testcontainers 自动将应用程序连接到名为 test 的数据库
综上所述,我相信数据库设置得很好,一切都应该很好
但是 当我在应用程序代码中使用 'current_setting('my.key')' 时失败
【问题讨论】:
如果在设置配置值后从初始化脚本中执行 我已经尝试过了,但它似乎没有任何效果。我遇到了与上述相同的问题。 【参考方案1】:如果要继续使用 JDBC URL 方案启动 Postgres 容器,请测试容器 can execute init script for you. 脚本必须在类路径中,引用如下:
jdbc:tc:postgis:9.6://hostname/databasename?TC_INITSCRIPT=somepath/init.sql
ALTER SYSTEM SET command was introduced in postgres 9.4,所以你可以在你的初始化脚本中使用它。
另一个选择是使用数据库容器对象启动 postgres 容器并使用 withCopyFileToContainer() 方法。示例:
JdbcDatabaseContainer<?> postgisContainer = new PostgisContainerProvider()
.newInstance()
.withDatabaseName( POSTGRES_DATABASE_NAME )
.withUsername( POSTGRES_CREDENTIALS )
.withPassword( POSTGRES_CREDENTIALS )
.withCopyFileToContainer(MountableFile.forClasspathResource("postgresql.conf"), "/var/lib/postgresql/data"));
编辑:
如果以上都不起作用,您可以重新配置 Postgres 命令并传递您的自定义配置键。您所需要的只是扩展 PostgreSQLContainer 并覆盖 configure() 方法。
@Override
protected void configure()
setCommand( "postgres -c $your_config_key=$your_config_value" );
【讨论】:
某些配置参数不能通过使用 SET 命令动态更改。例如,max_locks_per_transaction
config 需要重新启动服务器。我会尝试第二个选项,如果可行,我会回复你
为什么需要重写configure()
方法?我们不应该可以使用内置的GenericContainer.withCommand(String)
方法吗?
在检查 src 之后,我看到 PostgreSQLContainer 出于某种原因覆盖了configure()
并在其中调用了setCommand("postgres")
,这使得.withCommand()
无法与此容器一起使用。看起来像一个错误,所以我会尝试 PR
感谢@vilkq,但我想要的主要是确保:''通过 JDBC URL 方案启动'',正如您将看到的,在初始问题的 cmets 中,使用 init 脚本和更改系统命令来自 postgres 并没有帮助 - 这是同样的问题。【参考方案2】:
我们必须创建我们的数据库和连接的用户。这是通过使用 Docker 映像中的环境变量来完成的。要更改 postgres.conf,我们可以使用 DockerFIle,我们将用新配置替换现有的 postgres.conf。
@ClassRule
public static GenericContainer postgresql= new GenericContainer(
new ImageFromDockerfile("postgresql:10-alpine")
.withDockerfileFromBuilder(dockerfileBuilder ->
dockerfileBuilder.from("myPostgresql:10-alpine")
// root password is mandatory
.env("PG_ROOT_PASSWORD", "root_password")
.env("PG_DATABASE", "postgres")
.env("PG_USER", "postgres")
.env("PG_PASSWORD", "postgres")
)
接下来,我们必须创建一个数据库模式并填充数据库。从镜像文档中,目录 /docker-entrypoint-initdb.d 在启动时被扫描,所有带有 .sh、.sql 和 .sql.gz 扩展名的文件都会被执行。因此,我们只需要将文件 schema.sql 和 data.sql 放在此目录中。部分参数可以通过sql请求运行数据库来设置
.withFileFromClasspath("a_schema.sql", "db/pg/schema.sql")
.withFileFromClasspath("b_data.sql", "db/pg/data.sql"))
【讨论】:
我想使用“通过 JDBC URL 方案启动”而不是任何代码来解决这个问题。以上是关于使用 org.testcontainers 时如何在 docker 容器中包含 postgresql.conf的主要内容,如果未能解决你的问题,请参考以下文章
如何配置elasticsearch testcontainers 使用最新的ES
Spring testcontainers Driver org.testcontainers.jdbc.ContainerDatabaseDriver 声称不接受 jdbcUrl