You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

容器内通过Docker Socket执行PHP Curl请求失败求助

PHP通过Unix Socket调用Docker API失败排查

问题描述

我在Docker容器中运行PHP代码,想要执行等效于curl --unix-socket /var/run/docker.sock http://localhost/v1.40/containers/json的操作,获取宿主机上的容器列表。尝试了相关帖子中的两种方法,但既没有响应,STDERR也无输出,常遇到“Connection Failure”错误,curl_getinfo()返回的信息中http_code为0,各项传输相关数值均为0。

我的代码

<?php
function callAPI($method, $url, $data){
   $curl = curl_init();
   curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, "/var/run/docker.sock");
   curl_setopt($curl, CURLOPT_VERBOSE, true);
   switch ($method){
      case "POST":
         curl_setopt($curl, CURLOPT_POST, 1);
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
         break;
      case "PUT":
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);                               
         break;
      default:
         if ($data)
            $url = sprintf("%s?%s", $url, http_build_query($data));
   }
   // OPTIONS:
   curl_setopt($curl, CURLOPT_URL, $url);
   curl_setopt($curl, CURLOPT_HTTPHEADER, array(
      'Content-Type: application/json'
   ));
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   // EXECUTE:
   $result = curl_exec($curl);
   // echo $result;
   print_r($result);
   if(!$result){die("Connection Failure");}
   $info = curl_getinfo($curl);
   print_r($info);
   curl_close($curl);
   return $result;
}

$get_data = callAPI("GET","http://localhost/v1.40/containers/json", false);


print_r($get_data);
$response = json_decode($get_data, true);
$errors = $response['response']['errors'];
print_r($response);
echo $data;
echo $errors;
?>

错误输出

Array ( [url] => http://localhost/v1.40/containers/json [content_type] => [http_code] => 0 [header_size] => 0 [request_size] => 0 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0 [namelookup_time] => 2.1E-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] => [certinfo] => Array ( ) [primary_port] => 0 [local_ip] => [local_port] => 0 [http_version] => 0 [protocol] => 0 [ssl_verifyresult] => 0 [scheme] => )

问题排查与解决方法

1. 容器挂载与权限验证

首先确认容器是否正确挂载宿主机的/var/run/docker.sock,且PHP进程有读写权限:

  • 启动容器时必须添加挂载参数:-v /var/run/docker.sock:/var/run/docker.sock
  • 检查容器内/var/run/docker.sock的权限,确保PHP运行用户(通常是www-data)属于docker用户组,可在容器内执行chown root:docker /var/run/docker.sock,或启动容器时指定用户组:--group-add=$(stat -c '%g' /var/run/docker.sock)

2. 调整cURL选项顺序

部分cURL版本中,设置CURLOPT_URL会重置socket相关配置,需先设置URL再指定Unix Socket路径:

// 先设置URL
curl_setopt($curl, CURLOPT_URL, $url);
// 再设置Unix Socket路径
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, "/var/run/docker.sock");

3. 增强错误排查能力

在curl_exec后添加cURL错误信息输出,替换原die语句:

if(!$result){
    echo "cURL Error: " . curl_error($curl);
    die("Connection Failure");
}

这能直接定位具体错误,比如权限不足、socket文件不存在等。

4. 移除不必要的HTTP头部

Docker API的GET请求不需要Content-Type: application/json头部,可移除避免干扰:

// 仅在POST/PUT请求时添加Content-Type头部
if($method !== "GET"){
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
       'Content-Type: application/json'
    ));
}

修改后的示例代码

<?php
function callAPI($method, $url, $data){
   $curl = curl_init();
   // 先设置URL
   curl_setopt($curl, CURLOPT_URL, $url);
   // 再设置Unix Socket路径
   curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, "/var/run/docker.sock");
   curl_setopt($curl, CURLOPT_VERBOSE, true);
   switch ($method){
      case "POST":
         curl_setopt($curl, CURLOPT_POST, 1);
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
         break;
      case "PUT":
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);                               
         break;
      default:
         if ($data){
            $url = sprintf("%s?%s", $url, http_build_query($data));
            // 重新设置带参数的URL
            curl_setopt($curl, CURLOPT_URL, $url);
         }
   }
   // OPTIONS:
   // 仅非GET请求添加Content-Type头部
   if($method !== "GET"){
       curl_setopt($curl, CURLOPT_HTTPHEADER, array(
          'Content-Type: application/json'
       ));
   }
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   // EXECUTE:
   $result = curl_exec($curl);
   // 输出cURL错误信息
   if(!$result){
       echo "cURL Error: " . curl_error($curl);
       die("Connection Failure");
   }
   $info = curl_getinfo($curl);
   print_r($info);
   curl_close($curl);
   return $result;
}

$get_data = callAPI("GET","http://localhost/v1.40/containers/json", false);

print_r($get_data);
$response = json_decode($get_data, true);
print_r($response);
?>

内容的提问来源于stack exchange,提问作者masterlu12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 14:15:41