Docker网络中已暴露端口但API仍无法访问的排查求助
问题:.NET API无法通过Traefik或直接端口访问,健康检查失败
问题描述
部署VDS时,API既无法本地访问也无法通过网络访问,尝试Traefik反向代理和端口暴露均无效。API本身运行正常且已连接数据库,但外部无法访问,添加健康检查后直接失败。数据库、Traefik、前端应用配置均正常,仅后端API存在问题。
相关配置文件
Dockerfile
ARG DOTNET_SDK=mcr.microsoft.com/dotnet/sdk:8.0 FROM ${DOTNET_RUNTIME} AS base WORKDIR /app EXPOSE 5000 FROM ${DOTNET_SDK} AS build WORKDIR /src COPY ["CassiniConnect.API/CassiniConnect.API.csproj", "CassiniConnect.API/"] COPY ["CassiniConnect.Application/CassiniConnect.Application.csproj", "CassiniConnect.Application/"] COPY ["CassiniConnect.Core/CassiniConnect.Core.csproj", "CassiniConnect.Core/"] RUN dotnet restore "CassiniConnect.API/CassiniConnect.API.csproj" COPY . . ENV ASPNETCORE_URLS="http://+:5000" WORKDIR /src/CassiniConnect.API RUN dotnet publish "CassiniConnect.API.csproj" -c Release --no-restore -o /app/publish FROM base AS final WORKDIR /app ENV ASPNETCORE_ENVIRONMENT=Production COPY --from=build /app/publish . ENTRYPOINT [ "dotnet", "CassiniConnect.API.dll" ]
docker-compose.yaml
services: proxy: image: traefik:latest container_name: traefik command: - "--providers.docker" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=traefik" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - "--certificatesresolvers.myresolver.acme.httpchallenge=true" - "--certificatesresolvers.myresolver.acme.email=ujfalusiabel@cassini-org.info" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" - "--api.dashboard=true" ports: - "80:80" - "443:443" volumes: - letsencrypt:/letsencrypt - /var/run/docker.sock:/var/run/docker.sock networks: - traefik db: image: postgres:latest container_name: cassini-db restart: always env_file: - .env environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data networks: - traefik healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 10s timeout: 5s retries: 5 api: image: cassini-api:latest container_name: cassini-api restart: always depends_on: db: condition: service_healthy env_file: - .env environment: DefaultConnection: ${CONNECTION_STRING} JwtSettings__SecretKey: ${JwtSettings__SecretKey} JwtSettings__Issuer: ${JwtSettings__Issuer} JwtSettings__Audience: ${JwtSettings__Audience} ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT} volumes: - storage_data:/app/storage networks: - traefik labels: - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`api.cassini-org.info`)" - "traefik.http.routers.api.entrypoints=websecure" - "traefik.http.routers.api.tls.certresolver=myresolver" - "traefik.http.services.api.loadbalancer.server.port=5000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000/health"] interval: 10s timeout: 5s retries: 5 webapp: image: cassini-app:latest container_name: cassini-app restart: always depends_on: api: condition: service_healthy environment: - NEXT_APP_API_URL=https://api.cassini-org.info/api volumes: - webapp_data:/app/.next networks: - traefik labels: - "traefik.enable=true" - "traefik.http.routers.webapp.rule=Host(`cassini-org.info`)" - "traefik.http.routers.webapp.entrypoints=websecure" - "traefik.http.routers.webapp.tls.certresolver=myresolver" - "traefik.http.services.webapp.loadbalancer.server.port=3000" volumes: postgres_data: storage_data: webapp_data: letsencrypt: networks: traefik: name: traefik driver: bridge
排查与解决方案
1. 修复Dockerfile环境变量传递问题
ASPNETCORE_URLS变量在build阶段设置,但未传递到final运行阶段,导致.NET应用默认仅监听localhost,容器外部无法访问。修改Dockerfile,将该变量移至final阶段:
FROM base AS final WORKDIR /app ENV ASPNETCORE_ENVIRONMENT=Production ENV ASPNETCORE_URLS="http://+:5000" # 移至运行阶段 COPY --from=build /app/publish . ENTRYPOINT [ "dotnet", "CassiniConnect.API.dll" ]
2. 修复健康检查依赖缺失问题
默认的.NET ASP.NET镜像不带curl工具,导致健康检查命令执行失败。可选择以下三种方案:
- 方案1:改用wget(部分镜像内置):
healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://localhost:5000/health"] interval: 10s timeout: 5s retries: 5 - 方案2:检查端口而非HTTP接口:
需在Dockerfile的healthcheck: test: ["CMD", "nc", "-z", "localhost", "5000"] interval: 10s timeout: 5s retries: 5final阶段安装netcat:RUN apt-get update && apt-get install -y netcat-traditional && rm -rf /var/lib/apt/lists/* - 方案3:在镜像中安装curl:
在Dockerfile的final阶段添加:RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
3. 验证Traefik路由配置
- 确认
api.cassini-org.info的DNS记录已正确指向VDS公网IP - 查看Traefik日志,确认API服务是否被正确注册:
docker logs traefik - 验证API容器与Traefik在同一网络:
docker inspect cassini-api | grep "traefik"
4. 确认API端口监听状态
进入API容器,检查应用是否在监听0.0.0.0:5000:
docker exec -it cassini-api netstat -tulpn
若输出中无0.0.0.0:5000,则回到第一步确认ASPNETCORE_URLS配置是否生效。
内容的提问来源于stack exchange,提问作者Újfalusi Ábel
相关产品推荐
相关产品推荐

