首页 > 解决方案 > 在不知道主机操作系统的情况下访问主机上的 Docker 守护进程

问题描述

作为我正在开发的应用程序的一部分,我使用 docker-compose 来启动一些容器。其中一个容器需要在主机上启动一个 docker swarm 服务。在适用于 Windows 的 Docker 和适用于 Mac 的 Docker 上,我可以使用 REST Api 通过使用“host.docker.internal”DNS 名称连接到主机 docker 守护进程,这非常有效。但是,如果我在 linux 上运行相同的 compose 文件,“host.docker.internal”不起作用(但是,似乎它可能会出现在下一个版本的 docker 中)。更糟糕的是,在 Linux 上,我可以使用“主机”的网络模式来解决这个问题,但 Windows 或 Mac 不支持。

我怎么能:

  1. 无需创建多个 docker-compose.yml 文件或不同的应用程序代码,创建 docker-compose 文件或构建容器化应用程序以根据主机平台(windows|mac|linux)略有不同?
  2. 无论主机操作系统如何,都以一致的方式访问主机 docker 守护进程?

如果重要的话,正在访问主机的 docker 守护进程的容器正在使用 docker python sdk 并在没有 TLS 的情况下通过 tcp 对 docker 进行 api 调用(这仅用于开发)。

更新/解决方案详细信息

对于更多背景知识,有一个允许用户上传 zip 文件的 Web 应用程序 (aspnet core/C#)。除其他外,该 zip 文件包含一个导出的 docker 映像文件。在所有这些前面还有一个 nginx 容器,以允许 ssl 终止和负载平衡。Web 应用程序提取 docker 镜像,然后使用 docker 守护进程的 http api,加载镜像,重新标记镜像,然后将其推送到私有 docker 存储库(该存储库在开发人员网络的某个位置运行,在 docker 外部)。之后,它将消息发布到消息队列,其中一个单独的 python 应用程序使用 python docker 库将 docker 映像部署到 docker swarm。

出于开发目的,应用程序都作为容器运行,因此需要与运行在主机上的 docker 作为独立的 swarm 节点进行交互。SoftwareEngineer 的回答让我走上了正确的道路。我首先将主机中的 docker 套接字映射到 Web 应用程序容器中,但遇到了 .net 核心的限制,直到 .net 5 才能解决,也就是说没有通过 unix 套接字执行 http 的干净方法。

我最终意识到 nginx 可以将代理 http 流量反向到 unix 套接字,从而解决了这个问题。我将所有容器(包括从 zip 中动态加载的 swarm 服务)设置为覆盖网络的一部分,以使它们能够相互访问,并允许我访问 http 端点以通过 http 控制主机的 docker/swarm 守护进程。

我遇到的最后一个障碍是 nginx 无法写入 /var/run/docker.sock 文件中的映射,因此我修改了 nginx.conf 以允许它在容器中以 root 身份运行。

标签: dockerdocker-compose

解决方案


据我所知,docker 套接字/var/run/docker.sock在所有系统的路径上都可用。我已经使用最近的 Linux 发行版 (Ubuntu)、运行 Docker for Windows (2.2.0) 的 Windows 10 Pro 以及 WSL2(Ubuntu 和 Alpine)以及 windows cmd (cli) 和 powershell 亲自验证了这一点。从内存中,它也适用于 OSX,我曾经在 WSL1 中做同样的事情。

-v在任何带有、--volume--mount标志的终端上都可以将其映射到容器中。所以,

docker container run -v /var/run/docker.sock:/var/run/docker.sock

将套接字安装到容器内的相同路径中。这意味着您可以使用标准 docker 客户端 ( docker) 从容器内访问套接字,而无需额外配置。建议在 Linux 容器中使用此路径,因为这是标准位置,并且可能不会让将来维护您的代码的任何人(包括您自己)感到困惑。


推荐阅读