问题描述
在使用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文件,可以看到两个网络:sdnet
和net30
。确保主机和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
- 在主机的CLI中,获取Docker接口的IP地址。可以使用以下命令获取主机的Docker接口IP地址:
sudo ip addr show docker0
- 使用容器的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的问题。