【问题标题】:Docker API not accessible from within a container无法从容器内访问 Docker API
【发布时间】:2020-06-05 09:29:57
【问题描述】:

我可以对 Docker API 进行 cUrl 调用,但如果我从容器 (docker-compose) 运行相同的脚本,我将无法访问任何 API 端点。

我的请求看起来像:

$ curl --unix-socket /var/run/docker.sock -X POST http:/localhost/containers/json

原因可能是使用 localhost 但我现在找不到解决方案。有什么建议吗?

编辑:这是我正在使用的堆栈的简要摘要(Api-Platform https://api-platform.com/)。每个容器都附加到一个“api_default”桥接网络:

  • php = 基于 Symfony 的应用程序
  • nginx = NGINX 网络服务器
  • psql = 托管主数据库
  • mssql = 用于同步数据
  • ...

我的“php”容器中有一个用于访问 Docker API 的 shell 脚本。总而言之,我请求“mssql”容器与外部服务同步,然后请求“psql”容器复制这些数据(通过共享卷使用 csv 文件完成导出/导入)。

问题是:

  • 如果我执行docker-compose exec php bin/console app:sync(运行脚本的 Symfony 命令),一切正常:容器通过 docker.sock 与 Docker API 通信,我可以同步我的数据库。
  • 但是,如果我使用 api 端点 (localhost:8080/api/sync) 或通过 VueJS 应用程序 (Axios) 运行相同的脚本,Docker API 永远不会返回任何响应。

以下是我的脚本的一部分:

curl -XPOST -H 'Content-Type: application/json' \
      --unix-socket /var/run/docker.sock http:/localhost/containers/mssql/exec \
      -d '{
        "AttachStdout":true,
        "Tty":true,
        "Cmd":["/opt/mssql-tools/bin/sqlcmd", ...]
      }'

这是我在 api 端点控制器中调用 Symfony 命令的方式:

 /**
  * @Route("/api/sync", name="sync", methods={"GET"})
  */
  public function sync(KernelInterface $kernel)
  {
    $application = new Application($kernel);
    $application->setAutoExit(false);

    $input = new ArrayInput(array(
        'command' => 'app:sync'
    ));

    $output = new BufferedOutput();
    $application->run($input, $output);
    $content = $output->fetch();

    return new Response($content);
  }

也许我应该用“api_default”替换“localhost”以访问良好的网络,但这不起作用......?

【问题讨论】:

  • 您是否将 docker 套接字映射到容器中?你能提供给我们你的docker-compose.yml吗?
  • @RobertSeaman 是的,docker 套接字在我的调用中涉及的每个容器中都被映射为这样:volumes: - /var/run/docker.sock:/var/run/docker.sock
  • 检查this answer

标签: docker sockets curl docker-compose docker-api


【解决方案1】:

是的。如果要在一个 docker 容器和另一个 docker 容器之间进行通信,至少需要使用服务名称而不是 localhost,因为正如@BMW 所说,localhost 与您所在的机器相关,而从容器的角度来看,localhost就是容器本身。

我最近遇到过类似的情况,使用服务名称还不够。我还必须创建一个网络并将每个服务添加到该网络。像这样:

my_service:
    ...
    ...
    ...
    networks:
      - backend

networks:
  backend:
    driver: bridge

【讨论】:

  • 嗨,我的堆栈中已经有一个名为“api_default”的桥接网络。我怎么能达到它? curl http:/api_default/containers/json ?已经尝试过,但没有更多的运气......
  • 我认为,不要在 URI 中使用网络名称,而是使用服务名称。所以,my_service/containers/json...如果您正在努力寻找答案(就像我前一阵子一样),您可以使用docker exec -it container_name sh 在容器上打开一个外壳。然后你可以尝试从容器中 curl 看看有什么效果。
【解决方案2】:

您尝试连接的本地主机是您运行的容器中的本地主机curl

你应该找到并替换为它的主机 ip

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 2020-04-12
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多