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

问题描述 投票:1回答:1

有点背景,我有一个基于docker-compose的应用程序,有多个服务。每个服务可能有n个实例。我的服务间通信策略要求redis服务了解应用程序的当前状态,包括何时添加新实例以及实例何时死亡或被删除。

从阅读多篇博文和堆栈溢出问题,我知道解决方案涉及通过将unix socket /var/run/docker.sock绑定到容器中的套接字来与主机docker守护进程通信,但我无法获得任何牵引力。我遇到的大多数资源都给出了一个相当浅薄的解释,并且肯定缺少任何类型的ELI5教程。

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

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

我在其他帖子和堆栈溢出问题中已经看过几十次这个确切的片段,但解释通常会在那里结束。

在我的nodejs / express服务中,我创建了一个端点,用于测试我的设置是否正常工作。它使用Sindre Sorhus的got,因为它能够使用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'
}
sockets docker docker-compose communication unix-socket
1个回答
2
投票

可以使用HTTP端点与Docker守护程序API进行通信,并且默认情况下侦听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://containers/json
© www.soinside.com 2019 - 2024. All rights reserved.