Docker容器间无IP连接SQL Server及EF迁移构建问题求助
解决Docker中ASP.NET Core容器连接SQL Server容器的问题
我完全懂你的困扰——在Docker环境里用localhost或.连接数据库总是失败,每次部署新机器还要改连接字符串确实麻烦。让我一步步帮你搞定这个问题:
问题根源
每个Docker容器都是独立的网络环境,localhost在WebAPI容器里指向容器自身,根本不是宿主机或者SQL Server容器。Docker Compose会为服务创建专属网络,容器间可以通过服务名(比如你的db)互相访问,这才是正确的通信方式。
另外你提到构建时要执行EF迁移,这里还有两个容易踩的坑:
depends_on只保证容器启动顺序,不保证SQL Server服务已经就绪(SQL Server启动需要几十秒时间)- 构建阶段(
build)默认不在运行时的容器网络里,得特意配置让它能访问到db容器
完整解决方案
1. 修正docker-compose.yml配置
把两个容器放到同一个自定义网络里,移除外部nat网络(会导致服务名解析失效),同时统一数据库密码和连接字符串:
version: '3' services: webapi: image: webapi build: context: ./ dockerfile: ./WebAPI/Dockerfile args: - connString=Server=db;Database=YourDatabaseName;User Id=sa;Password=MyStrongPassword; environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:80 - conneString=Server=db;Database=YourDatabaseName;User Id=sa;Password=MyStrongPassword; ports: - 50695:80 depends_on: - db networks: - app-network db: image: "microsoft/mssql-server-linux:2017-latest" container_name: db environment: - ACCEPT_EULA=Y - MSSQL_SA_PASSWORD=MyStrongPassword ports: - 1433:1433 networks: - app-network networks: app-network: driver: bridge
2. 调整Dockerfile,添加数据库就绪等待脚本
SQL Server启动慢,直接跑迁移大概率会失败,我们需要一个等待脚本确保数据库完全就绪后再执行迁移:
FROM microsoft/aspnetcore:2.0 AS base WORKDIR /app EXPOSE 80 FROM microsoft/aspnetcore-build:2.0 AS build ARG connString ENV connString "$connString" # 安装netcat工具,用来检测SQL Server端口状态 RUN apt-get update && apt-get install -y netcat # 复制等待脚本到构建容器 COPY wait-for-db.sh /wait-for-db.sh RUN chmod +x /wait-for-db.sh WORKDIR /src COPY *.sln ./ COPY WebAPI/WebAPI.csproj WebAPI/ RUN dotnet restore COPY . . WORKDIR /src/Repository RUN dotnet restore # 等待SQL Server就绪后再执行EF迁移 RUN /wait-for-db.sh db 1433 -- dotnet ef database update WORKDIR /src/WebAPI RUN dotnet build -c Release -o /app FROM build AS publish RUN dotnet publish -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "WebAPI.dll"]
3. 创建wait-for-db.sh脚本
在项目根目录创建这个脚本(记得给它执行权限):
#!/bin/sh set -e host="$1" port="$2" shift 2 cmd="$@" # 循环检测SQL Server端口,直到可用 until nc -z "$host" "$port"; do >&2 echo "SQL Server is unavailable - sleeping for 1 second" sleep 1 done >&2 echo "SQL Server is up! Executing database migration..." exec $cmd
4. 部署步骤
现在不管在哪个新机器上,只需要执行以下命令就能完成部署:
# 先启动数据库容器(确保它就绪后再构建WebAPI) docker-compose up -d db # 构建并启动WebAPI容器 docker-compose up -d --build webapi
为什么这样能解决问题?
- 服务名代替IP:
Server=db在Docker网络里会自动解析到SQL Server容器的IP,不用手动修改连接字符串 - 等待脚本:解决了SQL Server启动慢导致的迁移失败问题
- 统一网络:自定义网络保证WebAPI和DB容器在同一网络环境,服务名解析完全正常
内容的提问来源于stack exchange,提问作者Islam El-Khayat
相关产品推荐
相关产品推荐

