JUnit Testcontainers的MySQL容器启动后如何导入SQL dump文件
问题根因
你遇到的命令解析失败核心原因是:execInContainer 默认直接启动指定的二进制程序,不会主动创建shell环境。而 < 是shell专属的输入重定向语法,直接作为参数传给mysql程序时会被识别为无效参数,因此输出mysql帮助信息。
你在CLI直接执行docker exec -i mycontainer mysql -uroot -proot myDatabase < init.sql能成功,是因为<是被宿主机的shell提前解析,把本地文件内容作为标准输入传给了容器内的mysql进程,和Java代码中把<作为参数传入容器的逻辑完全不同。
可行解决方案
方案1:通过shell包裹命令(符合你要求的容器内执行命令的需求)
把完整的mysql命令交给容器内的shell解释器执行,由shell处理重定向逻辑即可,修改init方法代码如下:
@PostConstruct @SneakyThrows public void init() { mySQLContainer.execInContainer("sh", "-c", "mysql -u root -proot myDatabase < init.sql"); }
方案2:使用Testcontainers MySQL原生初始化能力(更推荐)
Testcontainers的MySQL容器内置了初始化脚本支持,不需要手动复制文件、手动执行命令,只需要调用withInitScript方法指定类路径下的SQL文件即可,容器启动时会自动执行脚本完成初始化,示例代码如下:
public class AbstractTest { public static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:5.7") .withDatabaseName("myDatabase") // 直接传入类路径下的sql文件路径即可,Testcontainers自动处理执行逻辑 .withInitScript("init.sql") .withUsername("root") .withPassword("root"); static { mySQLContainer.start(); } // 无需手动编写init执行逻辑 }
该方案的原理是Testcontainers会自动把指定的SQL文件挂载到MySQL官方镜像默认的初始化目录/docker-entrypoint-initdb.d下,容器启动时会自动执行该目录下所有.sql后缀的文件,是官方推荐的初始化方式,稳定性更高。
内容的提问来源于stack exchange,提问作者Ilia
相关产品推荐
相关产品推荐

