Docker容器中Spring Boot连接MySQL时Flyway脚本执行失败求助
我有一个包含多个Flyway脚本的Spring Boot应用,这些脚本在非Docker环境下运行正常,但将应用放入Docker容器后出现问题。
相关配置
application.yml
server: port:8080 context-path:/tms-server http: mappers: jsonPrettyPrint:true security: basic: enabled:false cors: enabled:true flyway: enabled:true clean-on-validation-error:false validate-on-migrate:false url:jdbc:mysql://mysql-docker-container:3306/synfioo_poc?useSSL=false user:app_user password:test123 schemas:synfioo_poc locations:db/migration/mysql spring: profiles: active:mysql
application-mysql.yml
spring: jpa: database:mysql database-platform:org.hibernate.dialect.MySQL5Dialect datasource: url:jdbc:mysql://mysql-docker-container:3306/synfioo_poc?useSSL=false username:app_user password:test123 driver-class-name:com.mysql.jdbc.Driver
Flyway脚本(classpath:db/migration/mysql/V0001__R001_Create_schema.sql)
CREATE TABLE synfioo_poc.Binary_Object ( id BIGINT NOT NULL AUTO_INCREMENT, modification_counter INTEGER NOT NULL, data BLOB(2147483647), size BIGINT NOT NULL, mime_Type VARCHAR(255), PRIMARY KEY (ID) )
Docker运行命令
docker run -t --name synfioo-poc-container --link mysql-docker-container:mysql -p 8080:8080 docker-synfioo-core:latest
异常信息
2018-05-31 13:28:45.746 INFO 1 --- [ main] o.f.core.internal.util.VersionPrinter : Flyway 3.2.1 by Boxfuse 2018-05-31 13:28:46.783 INFO 1 --- [ main] o.f.c.i.dbsupport.DbSupportFactory : Database: jdbc:h2:mem:testdb (H2 1.4) 2018-05-31 13:28:47.457 INFO 1 --- [ main] o.f.core.internal.command.DbValidate : Validated 18 migrations (execution time 00:00.506s) 2018-05-31 13:28:47.502 INFO 1 --- [ main] o.f.c.i.metadatatable.MetaDataTableImpl : Creating Metadata table: "PUBLIC"."schema_version" 2018-05-31 13:28:47.609 INFO 1 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >> 2018-05-31 13:28:47.615 INFO 1 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version 0001 - R001 Create schema 2018-05-31 13:28:47.638 ERROR 1 --- [ main] o.f.core.internal.command.DbMigrate : Migration of schema "PUBLIC" to version 0001 failed! Please restore back ups and roll back database and code! 2018-05-31 13:28:47.670 WARN 1 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beansBatchConfig': Unsatisfied dependency expressed through method 'setTransactionManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.dbsupport.FlywaySqlScriptException: Migration V0001__R001_Create_schema.sql failed ---------------------------------------------- SQL State : 90079 Error Code : 90079 Message : Schema "SYNFIOO_POC" not found; SQL statement: CREATE TABLE synfioo_poc.Binary_Object ( id BIGINT NOT NULL AUTO_INCREMENT, modification_counter INTEGER NOT NULL, data BLOB(2147483647), size BIGINT NOT NULL, mime_Type VARCHAR(255), PRIMARY KEY (ID) ) [90079-193] Location : db/migration/mysql/V0001__R001_Create_schema.sql (/file:/synfioo-core-0.0.1-SNAPSHOT.jar!/db/migration/mysql/V0001__R001_Create_schema.sql) Line : 8 Statement : CREATE TABLE synfioo_poc.Binary_Object ( id BIGINT NOT NULL AUTO_INCREMENT, modification_counter INTEGER NOT NULL, data BLOB(2147483647), size BIGINT NOT NULL, mime_Type VARCHAR(255), PRIMARY KEY (ID) )
从异常日志里能一眼看到关键问题:Flyway没有连接你配置的MySQL,反而默认使用了H2内存数据库(日志里的Database: jdbc:h2:mem:testdb就是铁证)。下面一步步解决:
1. 确保Docker运行时激活MySQL Profile
你的主配置文件里指定了spring.profiles.active:mysql,但在Docker环境下可能没有正确生效。最稳妥的方式是在运行容器时通过环境变量明确指定激活的Profile:
docker run -t --name synfioo-poc-container --link mysql-docker-container:mysql -p 8080:8080 -e SPRING_PROFILES_ACTIVE=mysql docker-synfioo-core:latest
这样Spring Boot会加载application-mysql.yml里的MySQL数据源配置,Flyway也会正确连接到MySQL。
2. 确认MySQL中存在目标Schema
你的Flyway脚本直接在synfioo_poc下创建表,但如果这个Schema在MySQL中还不存在,即使连接正确也会报错。可以两种方式处理:
- 提前在MySQL容器中创建Schema:
docker exec -it mysql-docker-container mysql -u root -p -e "CREATE SCHEMA IF NOT EXISTS synfioo_poc;" - 或者在Flyway的第一个脚本开头添加创建Schema的语句:
CREATE SCHEMA IF NOT EXISTS synfioo_poc; CREATE TABLE synfioo_poc.Binary_Object ( id BIGINT NOT NULL AUTO_INCREMENT, modification_counter INTEGER NOT NULL, data BLOB(2147483647), size BIGINT NOT NULL, mime_Type VARCHAR(255), PRIMARY KEY (ID) )
3. 验证Docker容器间的网络连接
虽然你用了--link参数,但最好确认应用容器能正常访问MySQL容器:
# 进入应用容器 docker exec -it synfioo-poc-container bash # 尝试连接MySQL(需要容器内有mysql客户端,没有的话可以先安装) mysql -h mysql -u app_user -ptest123 synfioo_poc
如果能成功连接,说明网络没问题;如果连接失败,检查MySQL容器是否正常运行,或者改用Docker网络来替代--link(--link是比较旧的方式,推荐用自定义网络):
# 创建自定义网络 docker network create synfioo-network # 启动MySQL容器加入网络 docker run -d --name mysql-docker-container --network synfioo-network -e MYSQL_ROOT_PASSWORD=xxx -e MYSQL_DATABASE=synfioo_poc -e MYSQL_USER=app_user -e MYSQL_PASSWORD=test123 mysql:5.7 # 启动应用容器加入同一网络 docker run -t --name synfioo-poc-container --network synfioo-network -p 8080:8080 -e SPRING_PROFILES_ACTIVE=mysql docker-synfioo-core:latest
这样应用可以直接用mysql-docker-container作为主机名访问MySQL。
4. 检查Flyway配置与数据源的一致性
确保flyway.url和spring.datasource.url完全一致,包括主机名、端口、Schema参数。另外,如果你用的是Spring Boot 1.x版本(从Flyway 3.2.1来看应该是),Flyway会自动使用Spring的数据源,所以只要数据源配置正确,Flyway就会跟着用,不需要单独配置flyway.url、flyway.user这些,你可以尝试去掉主配置里的Flyway连接参数,让它自动复用Spring的数据源配置,避免配置不一致。
按照上面的步骤调整后,应该就能解决Flyway脚本执行失败的问题了!
内容的提问来源于stack exchange,提问作者user2579718

