sockets - 如何使用 unix 套接字从容器内部与 docker 守护进程进行通信?

标签 sockets docker docker-compose communication unix-socket

一些背景知识,我有一个基于 docker-compose 的应用程序,具有多个服务。每个服务可能有 n 个实例。我的服务间通信策略要求 Redis 服务了解应用程序的当前状态,包括何时添加新实例、何时终止或删除实例。

通过阅读多篇博客文章和堆栈溢出问题,我知道解决方案涉及通过将 unix 套接字 /var/run/docker.sock 绑定(bind)到套接字来与主机 docker 守护进程进行通信在容器中,但我无法获得任何牵引力。我遇到的大多数资源都对正在发生的事情给出了相当肤浅的解释,而且肯定缺乏任何类型的 ELI5 教程。

目前,在我的docker-compose.yml中,我有以下配置作为我的基于nodejs的服务之一的一部分(不,它不是redis服务的一部分,b/c我只是目前处于概念验证阶段)...

volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro

我在其他帖子和堆栈溢出问题中多次看到过这个确切的片段,但解释通常就到此为止。

在我的nodejs/express 服务中,我创建了一个端点,用于测试我的设置是否正常工作。它正在使用 got由 Sindre Sorhus 授予,因为它能够与 unix 套接字一起工作。

app.get('/dockersocket', async (req, res) => {
  const data = await got('unix:/var/run/docker.sock:/var/run/docker.sock')
  res.status(200).json({ data: data })
})

不用说,它在当前的形式下不起作用。当我将上面的代码片段包装在 try/catch 和 console.log 错误中时,我收到下面的输出...

{
  HTTPError: Response code 404(Not Found)
  at EventEmitter.emitter.on(/usr/src / app / node_modules / got / source / as - promise.js: 74: 19)
  at processTicksAndRejections(internal / process / next_tick.js: 81: 5)
  name: 'HTTPError',
  host: null,
  hostname: 'unix',
  method: 'GET',
  path: '/var/run/docker.sock',
  socketPath: '/var/run/docker.sock',
  protocol: 'http:',
  url: 'http://unix/var/run/docker.sock:/var/run/docker.sock',
  gotOptions: {
    path: '/var/run/docker.sock',
    protocol: 'http:',
    slashes: true,
    auth: null,
    host: null,
    port: null,
    hostname: 'unix',
    hash: null,
    search: null,
    query: null,
    pathname: '/var/run/docker.sock:/var/run/docker.sock',
    href: 'http://unix/var/run/docker.sock:/var/run/docker.sock',
    retry: {
      retries: [Function],
      methods: [Set],
      statusCodes: [Set],
      errorCodes: [Set]
    },
    headers: {
      'user-agent': 'got/9.6.0 (https://github.com/sindresorhus/got)',
      'accept-encoding': 'gzip, deflate'
    },
    hooks: {
      beforeRequest: [],
      beforeRedirect: [],
      beforeRetry: [],
      afterResponse: [],
      beforeError: [],
      init: []
    },
    decompress: true,
    throwHttpErrors: true,
    followRedirect: true,
    stream: false,
    form: false,
    json: false,
    cache: false,
    useElectronNet: false,
    socketPath: '/var/run/docker.sock',
    method: 'GET'
  },
  statusCode: 404,
  statusMessage: 'Not Found',
  headers: {
    'content-type': 'application/json',
    date: 'Sun, 31 Mar 2019 01:10:06 GMT',
    'content-length': '29',
    connection: 'close'
  },
  body: '{"message":"page not found"}\n'
}

最佳答案

Docker 守护进程 API 可以使用 HTTP 端点进行通信,并且默认情况下监听 UNIX 套接字。这意味着您可以像任何普通的 HTTP 服务器一样与它通信,只需在它是套接字时进行一些额外的处理即可。

您收到错误,因为虽然您确实向套接字发送了请求,但您请求了错误的路径。请求的语法是:

PROTOCOL://unix:SOCKET_PATH:ENDPOINT_PATH

对于您的代码,这意味着:

const data = await got('unix:/var/run/docker.sock:/var/run/docker.sock')

// protocol      = http (default by library)
// socket path   = /var/run/docker.sock
// endpoint path = /var/run/docker.sock

要解决您的问题,您应该请求有效的 Docker Engine API 端点 ( documentation for v1.39 ) 作为 HTTP 路径。列出容器的示例:

await got('unix:/var/run/docker.sock:/containers/json')

如果您有方便的 curl,您可以从 shell 中进行测试:

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

关于sockets - 如何使用 unix 套接字从容器内部与 docker 守护进程进行通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55437055/

相关文章:

node.js - docker npm安装错误-Kurento应用

docker - 将 Docker 容器 IP 添加到主机/etc/host

mysql - 我如何让 Lando mysql portforward 与 lamp 配方一起工作

azure - 从 Docker 容器将 Strapi SQLite 数据库保留在 Azure 应用服务 Linux 主机上

sockets - 从单个客户端到同一端口上同一服务器的最大连接数

sockets - 如果服务器不发送新行,如何读取服务器发送的数据(xml)

docker - 部署时如何启动新建的Docker镜像?

php - Docker:docker-compose 将文件从容器复制到主机

python - 套接字失去连接

python - 相同的错误代码