When run from the IDE the migrations are fine
Output:
INFO: Successfully applied 1 migration to schema `db`, now at version v1
But when I run the application from a container then Output:
example | Exception in thread "main"
example | org.flywaydb.core.api.FlywayException: Invalid SQL filenames found:
example | Unrecognised migration name format: V1__Example.sql
I have tried different Java versions. Going into the container itself and looking at the migration file, it looked ok. Maybe I can get some ideas from here?
Example code to reproduce the problem:
Applikation.kt
package com.example
import com.mysql.cj.jdbc.MysqlDataSource
import com.typesafe.config.ConfigFactory
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import org.flywaydb.core.Flyway
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
.start(wait = true)
}
fun Application.module() {
val conf = ConfigFactory.load()
val mysqlDataSource = MysqlDataSource()
mysqlDataSource.setURL(conf.getString("database.url"))
Flyway.configure().dataSource(
mysqlDataSource
)
.validateMigrationNaming(true)
.load()
.migrate()
}
Dockerfile
FROM gradle:7-jdk11 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle buildFatJar --no-daemon
FROM eclipse-temurin:11-jdk
EXPOSE 8080:8080
RUN mkdir /app
COPY --from=build /home/gradle/src/build/libs/*.jar /app/x.jar
ENTRYPOINT ["java","-jar","/app/x.jar"]
docker-compose.yml
version: '3.5'
services:
db:
image: mysql:8.0
container_name: db
restart: always
command: --default-authentication-plugin=caching_sha2_password
environment:
MYSQL_DATABASE: ${MYSQL_DB}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
ports:
- ${MYSQL_PORT}:${MYSQL_PORT}
expose:
- ${MYSQL_PORT}
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
interval: 5s
timeout: 5s
retries: 55
api:
image: example:test
container_name: example
ports:
- '8080:8080'
expose:
- '8080'
env_file: .env
depends_on:
db:
condition: service_healthy
dependencies
dependencies {
implementation("io.ktor:ktor-server-core-jvm")
implementation("io.ktor:ktor-server-netty-jvm")
implementation("org.flywaydb:flyway-core:9.20.0")
implementation("org.flywaydb:flyway-mysql:9.20.0")
implementation("mysql:mysql-connector-java:8.0.33")
}
You can see the full code in https://github.com/Skarpton/flyway-docker-problem
It looks like in docker the program cannot find any ResourceTypeProvider. This means that there are no prefixes configured.
Code:
fun Application.module() {
val conf = ConfigFactory.load()
val mysqlDataSource = MysqlDataSource()
mysqlDataSource.setURL(conf.getString("database.url"))
val load = Flyway.configure().dataSource(
mysqlDataSource
)
.validateMigrationNaming(true)
.load()
print(load.configuration.pluginRegister.getPlugins(ResourceTypeProvider::class.java)). //this is the interesting line
load.migrate()
}
Outputs in ide:
[org.flywaydb.core.internal.resource.CoreResourceTypeProvider@2381b1e8]
In docker:
[]
The problem was with building the fat jar. The problem was that the necessary plugins were not added to the META-INF/services/org.flywaydb.core.extensibility.Plugin file. I fixed it by using the shadowjar plugin with the configuration mergeServiceFiles(). I pushed the fixed version to the original repo https://github.com/Skarpton/flyway-docker-problem