Docker构建异常:SQL Server容器退出与ASP.NET API迁移问题解决
问题解决指南
一、SQL Server容器意外退出的修复
原因分析
docker-compose中mssql服务的自定义命令将sqlservr放到后台运行,执行完初始化脚本和sleep后,脚本进程结束,容器因主进程退出而停止。
修复步骤
修改docker-compose.yml中mssql服务的command,让sqlservr作为前台进程运行,同时正确处理初始化脚本的执行:
services: mssql: image: mcr.microsoft.com/mssql/server:2019-latest environment: SA_PASSWORD: "YourStrong!Passw0rd" ACCEPT_EULA: "Y" MSSQL_PID: "Developer" ports: - "1433:1433" volumes: - mssqldata:/var/opt/mssql - ./mssql-init:/mssql-init command: > /bin/bash -c " # 启动SQL Server并记录进程ID /opt/mssql/bin/sqlservr & SQLPID=$! # 轮询等待SQL Server可用 until /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourStrong!Passw0rd' -Q 'SELECT 1' 2>/dev/null; do sleep 1 done # 执行数据库初始化脚本 /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourStrong!Passw0rd' -i /mssql-init/init-database.sql # 等待主进程结束,防止容器退出 wait $SQLPID"
二、ASP.NET API容器构建失败与迁移问题修复
问题1:迁移文件缺失导致build失败
原因分析
Dockerfile的final阶段仅复制了csproj和发布后的文件,未包含Visual Studio生成的迁移文件(通常在Migrations目录下),dotnet ef database update需要这些文件才能执行构建和迁移操作。
修复步骤
修改ASP.NET API的Dockerfile,在final阶段复制迁移目录:
# Use the SDK image to build and publish the app FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY ["PaymentAPI/PaymentAPI.csproj", "PaymentAPI/"] RUN dotnet restore "PaymentAPI/PaymentAPI.csproj" COPY . . WORKDIR "/src/PaymentAPI" RUN dotnet build "PaymentAPI.csproj" -c Release -o /app/build RUN dotnet publish "PaymentAPI.csproj" -c Release -o /app/publish # Use the SDK image to run the app and perform migrations FROM mcr.microsoft.com/dotnet/sdk:8.0 AS final WORKDIR /app COPY --from=build /app/publish . # 复制迁移文件目录到容器 COPY --from=build /src/PaymentAPI/Migrations ./Migrations COPY --from=build /src/PaymentAPI/PaymentAPI.csproj /app/ COPY entrypoint.sh . RUN chmod +x entrypoint.sh RUN dotnet tool install --global dotnet-ef ENV PATH="$PATH:/root/.dotnet/tools" ENTRYPOINT ["./entrypoint.sh"]
问题2:API无法连接SQL Server容器
原因分析
API的数据库连接字符串若配置为localhost,在Docker容器环境中无法访问到mssql服务,需使用docker-compose中定义的服务名mssql作为数据库服务器地址。
修复步骤
修改API的appsettings.Development.json中的连接字符串:
{ "ConnectionStrings": { "DefaultConnection": "Server=mssql;Database=PaymentDatabase;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;" } }
问题3:entrypoint脚本优化
原因分析
原脚本中dotnet ef database update的输出被重定向,难以排查具体错误,且未针对容器环境优化连接检查逻辑。
修复步骤
修改entrypoint.sh,增加清晰日志输出并优化连接检查:
#!/bin/bash set -e run_cmd="dotnet PaymentAPI.dll" # 等待SQL Server容器可用 until /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P 'YourStrong!Passw0rd' -Q 'SELECT 1' 2>/dev/null; do >&2 echo "SQL Server is starting up, waiting..." sleep 2 done >&2 echo "SQL Server is up - executing database migrations" # 执行EF迁移 dotnet ef database update --project /app/PaymentAPI.csproj >&2 echo "Migrations completed - starting API service" exec $run_cmd
三、实现持续迁移机制
当前优化后的entrypoint脚本已包含dotnet ef database update步骤,只要迁移文件被正确复制到容器、连接字符串配置正确,每次API容器启动时都会自动检查并应用最新的迁移。
额外建议
- 将迁移文件纳入版本控制,确保代码更新时迁移文件同步到容器中
- 生产环境避免硬编码数据库密码,可使用Docker Secrets或环境变量管理敏感信息
内容的提问来源于stack exchange,提问作者Supernova-Ohee
相关产品推荐
相关产品推荐

