MySQL TestContainers init-script 模式创建失败
Posted
技术标签:
【中文标题】MySQL TestContainers init-script 模式创建失败【英文标题】:MySQL TestContainers init-script Schema Creation Failing 【发布时间】:2021-03-09 21:38:04 【问题描述】:尝试在 mysql 测试容器实例中创建架构时遇到以下问题。测试用户好像没有相应的权限?
配置:
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:mysql:5.7.22:///test?TC_INITSCRIPT=component/db/init_mysql.sql
Caused by: org.testcontainers.ext.ScriptUtils$UncategorizedScriptException: Failed to execute database script from resource [create schema new_schema CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;]
at org.testcontainers.ext.ScriptUtils.executeDatabaseScript(ScriptUtils.java:375)
at org.testcontainers.ext.ScriptUtils.executeDatabaseScript(ScriptUtils.java:313)
at org.testcontainers.jdbc.ContainerDatabaseDriver.runInitScriptIfRequired(ContainerDatabaseDriver.java:196)
at org.testcontainers.jdbc.ContainerDatabaseDriver.connect(ContainerDatabaseDriver.java:132)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:136)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467)
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:541)
... 61 more
Caused by: org.testcontainers.ext.ScriptUtils$ScriptStatementFailedException: Script execution failed (component/db/init_mysql.sql:1): create schema new_schema CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
at org.testcontainers.jdbc.JdbcDatabaseDelegate.execute(JdbcDatabaseDelegate.java:49)
at org.testcontainers.delegate.AbstractDatabaseDelegate.execute(AbstractDatabaseDelegate.java:34)
at org.testcontainers.ext.ScriptUtils.executeDatabaseScript(ScriptUtils.java:362)
... 69 more
Caused by: java.sql.SQLSyntaxErrorException: Access denied for user 'test'@'%' to database 'new_schema'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:782)
at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:666)
at org.testcontainers.jdbc.JdbcDatabaseDelegate.execute(JdbcDatabaseDelegate.java:42)
... 71 more
组件/db/init_mysql.sql
create schema new_schema CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
在 JDBC 集成之外创建 mysql 映像时遇到类似问题:
private static final MySQLContainer mysqlContainer = new MySQLContainer<>(DockerImageName.parse("mysql:5.7"))
.withInitScript("component/db/init_mysql.sql")
.withUsername("user")
.withPassword("password")
.withExposedPorts(3306)
.withReuse(true);
关于如何在不使用预先创建的架构创建自定义 docker 映像的情况下实现这一点的任何想法?
任何帮助将不胜感激我觉得我一定在这里遗漏了一些东西。
【问题讨论】:
也在这里提出github.com/testcontainers/testcontainers-java/issues/… 【参考方案1】:尝试创建 MySQL 容器并为root
使用与test
用户相同的密码,在本例中为whatever
。
@Container
private static MySQLContainer database = new MySQLContainer(MYSQL_DOCKER_TEST_VERSION)
.withUsername("test")
.withPassword("whatever")
...
通过@DynamicPropertySource 动态添加属性。
@DynamicPropertySource
static void databaseProperties(DynamicPropertyRegistry registry)
registry.add("spring.datasource.url", database::getJdbcUrl);
registry.add("spring.datasource.username", database::getUsername);
registry.add("spring.datasource.password", database::getPassword);
registry.add("flyway.user", () -> "root");
registry.add("flyway.password", database::getPassword);
我没有使用 flyway,但我相信它应该可以工作。
【讨论】:
【参考方案2】:正如在 testcontainers 存储库上创建的测试中所见,解决方法是指定 root 用户的密码并在测试中使用 root 用户:
MySQLContainer<?> db = new MySQLContainer<>(image)
.withUsername("test")
.withPassword("test")
.withEnv("MYSQL_ROOT_PASSWORD", "test")
...
参考:https://github.com/testcontainers/testcontainers-java/commit/2fa00ddbd1f42a20656d5e39d58cdedfbd483dcf#diff-f49cf0d09246a5351504ca32a08deb74e80ac7d61ad012f02d8f09c36508737bR65
【讨论】:
【参考方案3】:通过使用预先创建的模式创建自定义 MySQL 映像来解决此问题。很想知道是否有更好的方法。
【讨论】:
这不是一个坏方法,因为预创建的图像使容器启动时间更短。 您是如何实施此解决方案的?我有同样的问题,不胜感激。【参考方案4】:我遇到了同样的问题,我使用以下方法解决了它:
@Container
public static JdbcDatabaseContainer mariaDB = (JdbcDatabaseContainer) new MariaDBContainer("mariadb:10.5.11-focal")
.withDatabaseName("dbName")
.withInitScript("db.migration/init.sql")
.withUsername("your user")
.withPassword("your password")
.withUrlParam("param", "1")
.withUrlParam("param", "2");
基本上,我是通过 POJO 创建数据库的。有点hackish但有效。但也许使用自定义密码创建 root 用户是一个更好的解决方案。
【讨论】:
以上是关于MySQL TestContainers init-script 模式创建失败的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Testcontainers 将可执行文件复制到 Docker 容器
Spring testcontainers Driver org.testcontainers.jdbc.ContainerDatabaseDriver 声称不接受 jdbcUrl