Docker Compose部署ASP.NET与MSSQL时DBinit.sql未执行问题求助
问题根源
- Dockerfile配置错误:
ENTRYPOINT ["dotnet", "Server.dll"]和CMD /bin/bash ./entrypoint.sh逻辑冲突,最终容器启动时会将CMD内容作为参数传给ENTRYPOINT,导致entrypoint.sh完全未执行 - 原有
entrypoint.sh执行顺序错误:启动ASP.NET服务的前台进程会阻塞后续SQL脚本执行逻辑,就算脚本运行也永远走不到SQL执行步骤 - SQL连接地址错误:web容器内的
localhost指向web容器本身,无法连接到独立的db服务容器 - 官方ASP.NET镜像默认未安装mssql-tools,就算执行到sqlcmd命令也会报错找不到工具
解决方案
优先推荐数据库侧执行初始化的方案,逻辑更解耦,无需修改web服务配置:
方案一:数据库容器内部执行初始化(推荐)
1. 清理Dockerfile冗余逻辑
删除和数据库初始化相关的复制、执行逻辑,修复启动配置:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app COPY bin/Debug/net6.0/ ./ EXPOSE 80/tcp ENTRYPOINT ["dotnet", "Server.dll"]
2. 修改docker-compose.yml配置,为db服务添加初始化逻辑
version: "3.9" services: web: build: . ports: - "8000:80" depends_on: - db db: image: "mcr.microsoft.com/mssql/server" environment: SA_PASSWORD: "Your_password123" ACCEPT_EULA: "Y" volumes: # 挂载本地SQL脚本到db容器 - ./DBinit.sql:/DBinit.sql # 可选:挂载数据卷持久化数据库数据,避免重建容器丢失数据 - mssql_data:/var/opt/mssql entrypoint: ["/bin/bash", "-c"] command: - | # 后台启动SQL Server /opt/mssql/bin/sqlservr & MSSQL_PID=$! # 等待数据库启动完成 until /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "Your_password123" -d master -Q "SELECT 1" > /dev/null 2>&1; do sleep 1 done # 执行初始化脚本 /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "Your_password123" -d master -i /DBinit.sql # 挂载到SQL Server主进程,避免容器退出 wait $MSSQL_PID volumes: mssql_data:
3. 重启服务
删除原有entrypoint.sh,执行docker-compose down -v(删除旧的数据库卷,避免残留空库),再执行docker-compose up --build重新启动即可,数据库会在首次启动时自动执行初始化脚本。
方案二:保留在web容器执行初始化的逻辑
如果需要保留原有执行逻辑,可按以下步骤修改:
1. 修复Dockerfile配置
解决启动冲突,安装sqlcmd依赖:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app COPY bin/Debug/net6.0/ ./ COPY DBinit.sql ./ COPY entrypoint.sh ./ EXPOSE 80/tcp # 安装mssql-tools RUN apt-get update && apt-get install -y curl gnupg2 && \ curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ curl https://packages.microsoft.com/config/debian/11/prod.list > /etc/apt/sources.list.d/mssql-release.list && \ apt-get update && ACCEPT_EULA=Y apt-get install -y mssql-tools unixodbc-dev && \ chmod +x ./entrypoint.sh # 直接以entrypoint.sh作为启动入口 ENTRYPOINT ["/bin/bash", "./entrypoint.sh"]
2. 修改entrypoint.sh逻辑
调整执行顺序,修正数据库连接地址:
#!/bin/bash set -e # 等待数据库启动完成并执行EF迁移 until dotnet ef database update; do >&2 echo "等待SQL Server启动" sleep 1 done >&2 echo "SQL Server启动完成,执行初始化脚本" # 连接地址改为compose中的db服务名 /opt/mssql-tools/bin/sqlcmd -S db -U sa -P Your_password123 -d master -i /DBinit.sql >&2 echo "初始化完成,启动ASP.NET服务" # 最后启动web服务 dotnet Server.dll --urls http://*:80
3. 重启服务
执行docker-compose up --build重新构建启动即可。
内容的提问来源于stack exchange,提问作者Antonio Parroni
相关产品推荐
相关产品推荐

