当前位置: 首页 > 知识库问答 >
问题:

在使用docker compose的容器之间拒绝API请求的连接

夹谷茂
2023-03-14

我正在开发一个多容器的Docker应用程序,我想要一个容器使用Docker Compose向其他容器的API发出HTTP请求。我收到连接拒绝错误。

这两个容器都运行ASP.NET Core2.2。我使用的IDE是Visual Studio2017。我在用邮递员测试API调用。

DockerFiles

FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
...

Docker组合配置:

version: '3.4'

services:
  servicea:
    ...
    ports:
      - "51841:80"
      - "44364:443"
    networks:
      - local

  serviceb:
      ...
    ports:
      - "65112:80"
      - "44359:443"
    networks:
      - local

networks:
  local:
    driver: bridge

服务控制器操作:

[Route("[action]")]
[HttpGet]
public IActionResult foo()
{
   HttpClient client = _clientFactory.CreateClient();

   var result = client.GetAsync("http://serviceb:80/api/bar").Result;
   var response = result.Content.ReadAsStringAsync().Result;

   return new OkObjectResult(response);
}
System.Net.Http.HttpRequestException: Connection refused ---> System.Net.Sockets.SocketException: Connection refused
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
root@serviceA_id:/app# ping -p 80 serviceb
PATTERN: 0x80
PING serviceb(10.168.0.3) 56(84) bytes of data.
64 bytes from ... (10.168.0.3): icmp_seq=1 ttl=64 time=0.117 ms
64 bytes from ... (10.168.0.3): icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from ... (10.168.0.3): icmp_seq=3 ttl=64 time=0.083 ms
--- serviceb ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2057ms rtt min/avg/max/mdev = 0.083/0.100/0.117/0.016 ms

卷曲

我还可以使用CURL来稳定与API RESTendpoint的连接,但是recieved的Content-Length是0

root@serviceA_id:/app# curl -v http://serviceb/api/bar
*   Trying 10.168.0.3...
* TCP_NODELAY set
* Connected to serviceb (10.168.0.3) port 80 (#0)
> GET /api/bar/ HTTP/1.1
> Host: serviceb
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 307 Temporary Redirect
< Date: Mon, 17 Jun 2019 07:11:31 GMT
< Server: Kestrel
< Content-Length: 0
< Location: https://serviceb:44359/api/bar/
<
* Curl_http_done: called premature == 0
* Connection #0 to host serviceb left intact

因此,我们可以看到serviceB告诉serviceA它的请求将被重定向到https://serviceB:44359/api/bar/,但所需的连接端口是80(容器端口),而不是44359(主机端口)

root@serviceA_id:/app# curl -v -L http://serviceb/api/bar
*   Trying 10.168.0.3...
* TCP_NODELAY set
* Connected to serviceb (10.168.0.3) port 80 (#0)
> GET /api/bar HTTP/1.1
> Host: serviceb
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 307 Temporary Redirect
< Date: Wed, 19 Jun 2019 08:48:33 GMT
< Server: Kestrel
< Content-Length: 0
< Location: https://serviceb:44359/api/bar
<
* Curl_http_done: called premature == 0
* Connection #0 to host serviceb left intact
* Issue another request to this URL: 'https://serviceb:44359/api/bar'
*   Trying 10.168.0.3...
* TCP_NODELAY set
* connect to 10.168.0.3 port 44359 failed: Connection refused
* Failed to connect to serviceb port 44359: Connection refused
* Closing connection 1
curl: (7) Failed to connect to serviceb port 44359: Connection refused

为什么我被重定向到主机端口?

startup.cs中,我的服务使用app.usehttpsRedirection();,因此删除该行解决了问题

如果我还需要使用HTTPS怎么办?添加使用容器端口的选项。答案中的更多信息

共有1个答案

杨超
2023-03-14

ServiceA的HTTP请求被重定向(HTTP 307状态代码)到https://ServiceB:44359/API/BAR是HTTPS的主机端口:44359。容器之间不能访问主机端口,而容器端口可以访问。因此,如果我访问ServiceA的终端,并发送一个带有curlverbose-v的HTTP请求,该请求遵循重定向-l到URIHTTP://serviceB/API/BAR,我会收到连接拒绝错误:

root@serviceA_id:/app# curl -v -L http://serviceb/api/bar
*   Trying 10.168.0.3...
* TCP_NODELAY set
* Connected to serviceb (10.168.0.3) port 80 (#0)
> GET /api/bar HTTP/1.1
> Host: serviceb
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 307 Temporary Redirect
< Date: Wed, 19 Jun 2019 08:48:33 GMT
< Server: Kestrel
< Content-Length: 0
< Location: https://serviceb:44359/api/bar
<
* Curl_http_done: called premature == 0
* Connection #0 to host serviceb left intact
* Issue another request to this URL: 'https://serviceb:44359/api/bar'
*   Trying 10.168.0.3...
* TCP_NODELAY set
* connect to 10.168.0.3 port 44359 failed: Connection refused
* Failed to connect to serviceb port 44359: Connection refused
* Closing connection 1
curl: (7) Failed to connect to serviceb port 44359: Connection refused

为什么我被重定向到主机端口?

startup.cs中,我的服务使用了app.useHttpsRedirection();,这一行导致了问题。

HttpspolicyBuilderExtensions.UseHttpSRedirection(IApplicationBuilder)方法的默认配置默认重定向到HTTPS主机端口。如果要使用不同的端口进行重定向,则需要添加该选项,这样startup.cs将如下所示:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {

            ...

            services.AddHttpsRedirection(options =>
            {
                options.HttpsPort = 443;
            });

            ...

        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            ...

            app.UseHttpsRedirection();

            ...

        }
    }
 类似资料:
  • 问题内容: 我正在尝试设置一个docker- compose文件,该文件旨在用Supervisor替换运行多个进程(RQ worker,RQ仪表板和Flask应用程序)的单个Docker容器解决方案。 主机系统是Debian 8 Linux,我的样子如下(我删除了所有其他条目以减少错误源): “ rq-worker1”是Python RQ工作者,尝试通过本地主机和端口6379连接到Redis,但无

  • 试图在localhost中建立从app容器到mysql容器的连接,出现连接拒绝异常 我们正在采取一种docker的方法来调用rest api服务来采用微服务的方法。我们正在建立应用程序容器和mysql容器之间的连接,同时我们编写了一个docker-compose文件,创建了mysql容器和应用程序容器,为这两个容器公开了端口。下面是运行docker-compose文件docker-compose

  • 我试图测试一个具有类似下面的ELB的REST API:https://systemtest-inventory.com/v1/inventory/getinventory 当我用邮差chrome尝试URL时,它给了我有效的响应。但当我尝试在Java程序中使用它时,如下所示:

  • 我使用docker撰写启动一个mysql da和一个springstart应用程序。 这是我的docker-compose.yml 这是我的application.properties 在这里,我创建了jdbi: 不管我怎么做,我都无法让集装箱在码头内相互交谈。如果我单独启动sql,我可以在主机中看到连接(在datagrip中)。如果我从容器中运行java程序,它会看到主机中的数据库。即使我运行d

  • 我对PHP和XAMPP相当陌生。我现在正在用我的电脑开发Java和php。所以我的计算机中已经安装了mysql服务器。我成功地安装了xampp。但是当我试图访问phpMyAdmin时,它给我一个错误,说 (这不是实际错误,但这是它的意思..) 我尝试停止当前的MySQL服务并重新安装它。我尝试配置config.inc.php,我认为这是一种实现这一点的方法。但我对此无能为力。 谁能告诉我如何配置和

  • 问题内容: 我有一个运行Nginx的容器:; 并通过以下方式获取了其端口信息: 然后,我可以从容器中获取响应(ID:c30991a04b2f): =>返回默认页面内容,它可以正常工作 但是,当我在容器的外部制作时,得到了以下信息: 我在docker版本1.9.0的Mac上运行;Nginx最新 有谁知道是什么原因造成的?有什么帮助吗?谢谢 问题答案: 如果在OSX上,则可能是在docker环境中使用