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

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就绪后再启动:
    1. 把wait-for-it.sh脚本复制到后端项目根目录(如果不想用外链,也可以手动创建这个脚本)
    2. 修改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

最后验证步骤

  1. 清理旧容器和数据卷:docker-compose down -v
  2. 重新构建并启动:docker-compose up --build
  3. 查看后端日志:docker logs backend,确认是否还有连接错误。

如果还是有问题,可以查看PostgreSQL容器日志:docker logs message,排查数据库初始化是否有异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 18:42:31