Docker环境下.NET Core后端启动失败(数据库连接拒绝)及与Nginx前端通信问题求助
Hey Marco,我仔细看了你的配置和错误信息,发现几个关键问题导致你的.NET Core后端连不上PostgreSQL,咱们一步步来解决:
从错误日志System.Net.Sockets.SocketException (111): Connection refused能看出,后端容器无法建立到PostgreSQL的连接,结合你的配置,主要有以下几个核心问题:
1. Dockerfile中.NET版本不兼容+端口暴露错误
你构建阶段用的是.NET 5.0 SDK,但运行时却用了.NET 3.1 ASP.NET Runtime,版本不匹配会导致编译后的程序在低版本运行时中出现兼容性问题,甚至直接启动失败。另外,你错误地暴露了PostgreSQL的5432端口,后端应用不需要这个,应该暴露.NET Core默认的80或5000端口。
修复后的Dockerfile:
# syntax=docker/dockerfile:1 # 统一使用.NET 5.0版本(如果课程要求用3.1,就把所有5.0替换成3.1) FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env WORKDIR /app # Copy csproj and restore as distinct layers COPY *.csproj ./ RUN dotnet restore # Copy everything else and build COPY . ./ RUN dotnet publish -c Release -o out # 运行时镜像与SDK版本保持一致 FROM mcr.microsoft.com/dotnet/aspnet:5.0 WORKDIR /app COPY --from=build-env /app/out . # 暴露.NET Core默认的HTTP端口(容器内部端口,和宿主映射无关) EXPOSE 80 ENTRYPOINT ["dotnet", "backend.dll"]
2. Docker Compose中依赖关系+环境变量配置错误
在你修改后的docker-compose.yml里,有两个明显的错误:
- 后端的
depends_on写的是message(容器名),但Docker Compose内部是通过服务名通信的,你的PostgreSQL服务名是db,所以这里应该写db。 - 后端配置了无用的Nginx目录挂载
./src:/usr/share/nginx/html,这是前端容器的配置,后端完全不需要,会造成不必要的文件冲突。
修正后的后端服务配置:
backend: container_name: 'backend' depends_on: - db # 这里必须写服务名,不是容器名 build: context: ./backend/ dockerfile: ./Dockerfile # 删掉无用的Nginx挂载 environment: - ConnectionStrings__DefaultConnection=Host=db;database=message;Username=postgres;Password=6AX3PwqM47fZAHw9 ports: - "5000:80" # 宿主端口5000映射到容器内部的80端口(和EXPOSE对应) networks: - marco-network
3. depends_on不等待数据库就绪的局限性
Docker Compose的depends_on只是保证启动顺序,不会等待PostgreSQL完全就绪(比如数据库初始化完成、可以接受连接)。后端启动时,数据库可能还在初始化,自然会抛出连接拒绝的错误。
解决方法二选一:
- 方案1:在后端代码中添加连接重试逻辑,比如在DbContext初始化或数据库迁移的代码里,增加循环重试机制,直到连接成功。
- 方案2:使用
wait-for-it脚本让后端容器等待PostgreSQL就绪后再启动:- 把wait-for-it.sh脚本复制到后端项目根目录(如果不想用外链,也可以手动创建这个脚本)
- 修改Dockerfile添加脚本:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 WORKDIR /app COPY --from=build-env /app/out . COPY wait-for-it.sh ./ RUN chmod +x wait-for-it.sh EXPOSE 80 # 等待db的5432端口就绪后再启动后端 ENTRYPOINT ["./wait-for-it.sh", "db:5432", "--", "dotnet", "backend.dll"]
4. PostgreSQL服务的健康检查与初始化验证
如果用自定义PostgreSQL Dockerfile,要确保它正确初始化了message数据库和对应的用户。如果用官方镜像,建议添加健康检查,让Compose知道数据库什么时候真正就绪:
db: container_name: 'message' image: postgres:latest # 用官方镜像更稳妥,除非有特殊自定义需求 environment: - POSTGRES_DB=message - POSTGRES_USER=postgres - POSTGRES_PASSWORD=6AX3PwqM47fZAHw9 ports: - 5432:5432 networks: - marco-network # 添加健康检查,确认数据库可连接 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d message"] interval: 5s timeout: 5s retries: 5
然后后端的depends_on可以改成等待健康检查通过:
backend: # ...其他配置 depends_on: db: condition: service_healthy
最后验证步骤
- 清理旧容器和数据卷:
docker-compose down -v - 重新构建并启动:
docker-compose up --build - 查看后端日志:
docker logs backend,确认是否还有连接错误。
如果还是有问题,可以查看PostgreSQL容器日志:docker logs message,排查数据库初始化是否有异常。
内容的提问来源于stack exchange,提问作者Marco Tidu

