You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试数据库迁移失效求助:Testcontainers与Flyway配置排查

测试环境PostgreSQL数据库迁移失效排查求助

我正尝试为测试环境迁移testdb数据库,除迁移操作外其他功能均正常,迁移文件目录也配置正确,但迁移始终无法生效。请帮忙排查问题,测试时的相关代码如下:

describe("ApiTable", () => {
  let container: StartedTestContainer;
  let flywayContainer: StartedTestContainer;
  let db: Kysely<DB>;

  beforeAll(async () => {
    // 使用Testcontainers创建PostgreSQL数据库
    container = await new GenericContainer("postgres")
      .withExposedPorts(5432)
      .withEnvironment({ POSTGRES_USER: "postgres" })
      .withEnvironment({ POSTGRES_PASSWORD: "password" })
      .withEnvironment({ POSTGRES_DB: "testdb" })
      .start();

    const host = container.getHost();
    const port = container.getMappedPort(5432);
    const username = "postgres";
    const password = "password"; 
    const database = "testdb";

    // 将数据库连接信息设置为环境变量
    process.env.DB_HOST = host;
    process.env.DB_PORT = port.toString();
    process.env.DB_USERNAME = username;
    process.env.DB_PASSWORD = password;
    process.env.DB_DATABASE = database;

    // 启动Flyway Docker容器并针对Postgres容器执行迁移
    flywayContainer = await new GenericContainer("flyway/flyway")
      .withCommand([
        "-url=jdbc:postgresql://"+username+":"+password+"@"+host+':'+port+'/' + database,
        "-user="+username,
        "-password="+password,
        "migrate"
      ])
      .withBindMounts([{ 
        source: __dirname + '/../../../../../sql', 
        target:"/flyway/sql" 
      }])
      .start();

    db = new Kysely<DB>({
      dialect: new PostgresDialect({
        pool: new Pool({
          connectionString: "postgresql://"+username+":"+password+"@"+host+':'+port+'/' + database,
        }),
      }),
    });
  }, 50000);
});

排查与修复建议

1. 修正Flyway JDBC连接URL

当前URL格式错误,PostgreSQL JDBC URL无需将用户名密码嵌入主机地址部分,正确格式配合-user/-password参数使用即可:

.withCommand([
  `-url=jdbc:postgresql://${host}:${port}/${database}`,
  `-user=${username}`,
  `-password=${password}`,
  "migrate"
])

2. 等待Flyway迁移完成再初始化数据库连接

start()启动容器后会立即返回,但Flyway迁移需要时间执行,必须等待迁移完成后再创建Kysely连接:

// 等待迁移成功日志输出,超时时间30秒
await flywayContainer.waitForLogMessage("Successfully applied", 30000);

// 再初始化Kysely连接
db = new Kysely<DB>({
  // ... 原有配置
});

3. 检查迁移文件命名规范

Flyway要求迁移文件必须遵循V<版本号>__<描述>.sql格式(例如V1__init_tables.sql),确保sql目录下的文件完全符合该规则,否则会被Flyway忽略。

4. 验证挂载路径的正确性与权限

  • 使用path.resolve()替代字符串拼接路径,避免相对路径解析错误:
    import path from 'path';
    // ...
    .withBindMounts([{ 
      source: path.resolve(__dirname, '../../../../../sql'), 
      target: "/flyway/sql" 
    }])
    
  • 若存在权限问题,可添加.withPrivilegedMode(true)赋予容器更高权限:
    flywayContainer = await new GenericContainer("flyway/flyway")
      .withPrivilegedMode(true)
      // ... 其他配置
      .start();
    

5. 查看Flyway执行日志

通过容器日志排查具体错误:

// 启动后打印Flyway日志
const logs = await flywayContainer.logs();
console.log("Flyway logs:", logs);

内容的提问来源于stack exchange,提问作者Ayushman Dixit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 18:23:21