Docker容器内调用API报错:目标机器主动拒绝连接
问题:Docker容器内调用API连接被拒绝
HttpRequestException: No connection could be made because the target machine actively refused it. (localhost:21000)
前后端部署在同一机器上,直接在浏览器访问http://localhost:21000/WeatherForecast可正常运行,但前端容器内调用API时报错。相关配置如下:
前端Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build WORKDIR /src COPY ["DockerBasicClientServe2/DockerBasicClientServe2.csproj", "DockerBasicClientServe2/"] RUN dotnet restore "DockerBasicClientServe2/DockerBasicClientServe2.csproj" COPY . . WORKDIR "/src/DockerBasicClientServe2" RUN dotnet build "DockerBasicClientServe2.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "DockerBasicClientServe2.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "DockerBasicClientServe2.dll"]
API的Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base WORKDIR /app EXPOSE 80 FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build WORKDIR /src COPY ["MyRestApi/MyRestApi.csproj", "MyRestApi/"] RUN dotnet restore "MyRestApi/MyRestApi.csproj" COPY . . WORKDIR "/src/MyRestApi" RUN dotnet build "MyRestApi.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "MyRestApi.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "MyRestApi.dll"]
docker-compose.yml
version: '3.4' services: dockerbasicclientserve2: image: ${DOCKER_REGISTRY-}dockerbasicclientserve2 build: context: . dockerfile: DockerBasicClientServe2\Dockerfile ports: - "5200:80" - "5201:443" myrestapi: image: ${DOCKER_REGISTRY-}myrestapi build: context: . dockerfile: MyRestApi\Dockerfile ports: - "21000:80"
调用API的代码
public async Task<IActionResult> Weather() { var weatherForeCastResponse = await this._client.GetAsync("http://localhost:21000/WeatherForecast"); var temp = await weatherForeCastResponse.Content.ReadAsStringAsync(); var weatherForeCast = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(temp); return View(weatherForeCast); }
解决方案
1. 修改API调用地址
将前端代码中的http://localhost:21000/WeatherForecast替换为http://myrestapi:80/WeatherForecast,修改后代码如下:
public async Task<IActionResult> Weather() { var weatherForeCastResponse = await this._client.GetAsync("http://myrestapi:80/WeatherForecast"); var temp = await weatherForeCastResponse.Content.ReadAsStringAsync(); var weatherForeCast = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(temp); return View(weatherForeCast); }
2. (可选)通过环境变量配置地址
为提升灵活性,建议将API地址配置为环境变量:
- 在
docker-compose.yml的dockerbasicclientserve2服务下添加环境变量:
environment: - ApiBaseUrl=http://myrestapi:80
- 在前端项目中读取环境变量并使用:
var apiUrl = Environment.GetEnvironmentVariable("ApiBaseUrl") ?? "http://localhost:21000"; var weatherForeCastResponse = await this._client.GetAsync($"{apiUrl}/WeatherForecast");
原因说明
- Docker容器内的
localhost指向容器自身,而非宿主机。前端容器访问localhost:21000时,实际是在访问容器自己的21000端口,而非宿主机上映射的API端口。 - Docker Compose会自动为同一网络下的服务创建DNS解析,服务名(
myrestapi)可直接作为域名访问对应容器,端口使用容器内部暴露的80端口(无需使用宿主机的21000端口)。
内容的提问来源于stack exchange,提问作者Amokachi
相关产品推荐
相关产品推荐

