在Docker容器内部,如何访问主机的localhost上的API

46次阅读
没有评论

问题描述

在使用Docker容器时,希望从容器内部访问主机的localhost上的API。用户的系统是基于Ubuntu 20.2,Docker版本是20.10.10。用户的系统是基于CakePHP的Docker容器,而API是运行在主机的localhost上的(不在Docker容器内部),用户需要从容器内部的系统中消费该API。

用户提供的docker-compose.yml文件内容如下:

version: '2'
services:
  server-c10-php56:
    build:
      context: .
      dockerfile: Dockerfile
    image: php-c10-56
    volumes:
      - /srv/:/srv/
      - /var/www/html/:/var/www/html/
    ports:
      - "9056:80"
      - "9443:443"
    networks:
      - net30
    container_name: "docker-php56"
networks:
  sdnet:
    driver: "bridge"
  net30:
    ipam:
      driver: default
      config:
        - subnet: 172.30.0.0/16

根据用户的理解,CakePHP系统运行在172.30.0.0/16子网内。而系统连接到PostgreSQL时,通过IP地址172.30.0.1进行连接(用户认为这是访问主机localhost的网关)。

用户可以通过Postman正常访问API,但在Docker容器内部的系统中尝试访问时,连接一直失败。以下是用户获取的返回结果(对于数组格式表示抱歉):

Array(
    [response] => 
    [info] => Array
        (
            [url] => http://172.30.0.1:8000/api/queue/integracaoEcommerce
            [content_type] => 
            [http_code] => 0
            [header_size] => 0
            [request_size] => 0
            [filetime] => -1
            [ssl_verify_result] => 0
            [redirect_count] => 0
            [total_time] => 130.124754
            [namelookup_time] => 1.8E-5
            [connect_time] => 0
            [pretransfer_time] => 0
            [size_upload] => 0
            [size_download] => 0
            [speed_download] => 0
            [speed_upload] => 0
            [download_content_length] => -1
            [upload_content_length] => -1
            [starttransfer_time] => 0
            [redirect_time] => 0
            [redirect_url] => 
            [primary_ip] => 172.30.0.1
            [certinfo] => Array
                (
                )
            [primary_port] => 8000
            [local_ip] => 
            [local_port] => 0
        )
)

用户还提供了用于调用API的方法(如果这些信息重要的话):

private function callAPI($options){
    extract($options);
    $ch = curl_init();
    $header = array(
        "Content-Type: application/json",
        "Authentication: bearer {$integrador['token']}"
    );
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    if(!empty($data) OR $verb == 'POST'){
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_POST, TRUE);
    }
    if($verb)
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $verb);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    $response = curl_exec($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);
    return array('response' => $response, 'info' => $info);
}

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

在Docker容器内部访问主机的localhost上的API,可以使用Docker的网络配置来实现。以下是解决方案的步骤:
1. 确保Docker容器和主机在同一个网络中。根据用户提供的docker-compose.yml文件,可以看到两个网络:sdnetnet30。确保主机和Docker容器都连接到同一个网络。
2. 在Docker容器内部,使用主机的IP地址来访问API。根据用户提供的信息,主机的IP地址是172.30.0.1。在Docker容器内部的系统中,将API的URL修改为http://172.30.0.1:8000/api/queue/integracaoEcommerce

请注意,这种方法假设主机的IP地址在Docker容器内部是可访问的。如果主机的IP地址在Docker容器内部不可访问,则需要使用其他方法,如端口映射或使用Docker的网络代理。

方案2

如果方案1无法解决问题,可以尝试使用Docker的网络代理来访问主机的localhost上的API。请注意,这种方法可能会有一些安全风险,请谨慎使用。
以下是解决方案的步骤:
1. 在Docker容器内部,获取容器的IP地址。可以使用以下命令在容器的CLI中获取IP地址:

ip addr show eth0
  1. 在主机的CLI中,获取Docker接口的IP地址。可以使用以下命令获取主机的Docker接口IP地址:
sudo ip addr show docker0
  1. 使用容器的IP地址和主机的Docker接口IP地址来访问API。根据用户提供的信息,容器的IP地址是172.30.0.1,主机的Docker接口IP地址是172.30.0.1。在Docker容器内部的系统中,将API的URL修改为http://172.30.0.1:8000/api/queue/integracaoEcommerce

请注意,使用Docker的网络代理可能会导致安全风险,请确保在使用之前评估和采取适当的安全措施。

方案3

如果以上两种方案都无法解决问题,可以参考以下链接,其中提供了一些其他可能的解决方案:
https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach

请注意,这些解决方案可能因环境和配置的不同而有所差异,请根据实际情况选择适合的解决方案。

以上是解决方案的几种可能方法,根据用户提供的信息,您可以尝试其中一种方法来解决在Docker容器内部访问主机的localhost上的API的问题。

正文完