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

Docker容器重启后ASP.NET Core的Database.Migrate执行失败

问题描述

我将ASP.NET Core Web API部署在Docker中,应用与容器内的SQL Server进行交互。docker-compose.yml配置如下:

version: '3'
services:
    db:
        image: mcr.microsoft.com/mssql/server
        container_name: db
        ports:
            - 1533:1433
        environment:
            - TZ=Asia/Tehran
            - ACCEPT_EULA=Y
            - MSSQL_SA_PASSWORD=******
        user: root
        volumes:
            - ./mssql:/var/opt/mssql/data
    kava-service:
        image: service:1.0.0
        container_name: service
        expose:
            - 9001
        ports:
            - 9001:9001
        depends_on:
            - db
        environment:
            - ASPNETCORE__ENVIRONMENT=Production
            - TZ=Asia/Tehran
            - AUTO__MIGRATE=true
            - ConnectionStrings__BusinessDomainConnectionString=Server=db;Initial Catalog=Kava.BusinessDomain;User ID=sa;pwd=****;MultipleActiveResultSets=true;
            - ConnectionStrings__RecordsConnectionString=Server=db;Initial Catalog=Kava.Records;User Id=sa;pwd=****;MultipleActiveResultSets=true;

首次通过docker-compose启动容器运行正常,但重启容器后应用退出,报错信息:

Login failed for user 'sa'. Reason: Failed to open the explicitly specified database 'Kava.BusinessDomain' [CLIENT: 172.18.0.4] kava-service
Unhandled exception. Microsoft.Data.SqlClient.SqlException (0x80131904): Database 'Kava.BusinessDomain' already exists. Choose a different database name.

删除数据库后可恢复正常,但我希望保留数据库。开发环境(Visual Studio)中一切正常,但Docker生产环境的数据迁移不符合预期。迁移代码如下:

BusinessDomainContext businessDomainContext = serviceScope.ServiceProvider.GetRequiredService<IBusinessDomainDatabaseFactory>().Get() as BusinessDomainContext;
await businessDomainContext.Database.MigrateAsync();

解决方案

1. 修复SQL Server容器的用户权限问题

SQL Server官方镜像默认要求以mssql用户运行,配置user: root会导致挂载的数据目录权限异常,重启后数据库文件无法正常加载,引发"找不到数据库"和"数据库已存在"的冲突报错。

修改db服务配置,移除user: root:

db:
    image: mcr.microsoft.com/mssql/server
    container_name: db
    ports:
        - 1533:1433
    environment:
        - TZ=Asia/Tehran
        - ACCEPT_EULA=Y
        - MSSQL_SA_PASSWORD=******
    volumes:
        - ./mssql:/var/opt/mssql/data

如果之前已用root运行过容器,需重置挂载目录权限:

# 容器内调整目录权限
docker exec -it db chown -R mssql:mssql /var/opt/mssql/data
# 或本地目录权限调整
sudo chown -R 10001:10001 ./mssql

2. 确保应用在SQL Server完全就绪后再启动

depends_on仅保证db容器启动,不确保SQL Server服务完全就绪。重启时应用可能在数据库未加载完成时就尝试连接,后续迁移逻辑又触发创建已存在数据库的冲突。

在应用启动时添加连接检测逻辑,直到SQL Server就绪再执行迁移:

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // 注册你的服务依赖
    })
    .Build();

// 检测SQL Server连接可用性
using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var logger = services.GetRequiredService<ILogger<Program>>();
    var retryCount = 0;
    const int maxRetries = 10;

    while (retryCount < maxRetries)
    {
        try
        {
            var context = services.GetRequiredService<IBusinessDomainDatabaseFactory>().Get() as BusinessDomainContext;
            await context.Database.OpenConnectionAsync();
            logger.LogInformation("SQL Server连接成功");
            await context.Database.CloseConnectionAsync();
            break;
        }
        catch (Exception ex)
        {
            retryCount++;
            logger.LogWarning(ex, $"连接SQL Server失败,重试第{retryCount}次");
            await Task.Delay(2000);
            
            if (retryCount == maxRetries)
            {
                logger.LogCritical("重试多次后仍无法连接SQL Server,退出应用");
                throw;
            }
        }
    }
}

// 执行数据迁移
using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var businessDomainContext = services.GetRequiredService<IBusinessDomainDatabaseFactory>().Get() as BusinessDomainContext;
    await businessDomainContext.Database.MigrateAsync();
}

await host.RunAsync();

3. 清理迁移逻辑中的冲突代码

检查DbContext相关代码,确保没有同时使用EnsureCreatedAsync()和MigrateAsync()。EnsureCreatedAsync()会直接创建数据库但不应用迁移,和MigrateAsync()混用会导致"数据库已存在"的冲突,只保留MigrateAsync()即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:45:04