Sockets 如何使用unix套接字从容器内部与docker守护进程通信?
有一点背景知识,我有一个基于docker compose的应用程序,具有多个服务。每个服务可能有n个实例。我的服务间通信策略要求redis服务了解应用程序的当前状态,包括何时添加新实例,何时实例死亡或移除 通过阅读多篇博客文章和堆栈溢出问题,我知道解决方案涉及通过将unix套接字Sockets 如何使用unix套接字从容器内部与docker守护进程通信?,sockets,docker,docker-compose,communication,unix-socket,Sockets,Docker,Docker Compose,Communication,Unix Socket,有一点背景知识,我有一个基于docker compose的应用程序,具有多个服务。每个服务可能有n个实例。我的服务间通信策略要求redis服务了解应用程序的当前状态,包括何时添加新实例,何时实例死亡或移除 通过阅读多篇博客文章和堆栈溢出问题,我知道解决方案涉及通过将unix套接字/var/run/docker.sock绑定到容器中的套接字来与主机docker守护程序通信,但我无法获得任何帮助。我遇到的大多数资源都对正在发生的事情给出了一个相当肤浅的解释,而且肯定缺少任何形式的ELI5教程 目前,
/var/run/docker.sock
绑定到容器中的套接字来与主机docker守护程序通信,但我无法获得任何帮助。我遇到的大多数资源都对正在发生的事情给出了一个相当肤浅的解释,而且肯定缺少任何形式的ELI5教程
目前,在我的docker compose.yml
中,我将以下配置作为基于nodejs的服务之一的一部分(不,它不是redis服务b/c的一部分,我目前正处于概念验证阶段)
我在其他帖子和堆栈溢出问题中多次看到这个片段,但解释通常到此为止
在nodejs/express服务中,我创建了一个端点,用于测试我的设置是否正常。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引擎API端点()作为HTTP路径。列出容器的示例:
await got('unix:/var/run/docker.sock:/containers/json')
如果您手边有curl
工具,您可以从shell中进行测试:
$ curl --unix-socket /var/run/docker.sock http://containers/json
感谢您的解释和文档链接。我以前从未遇到过这种情况。我现在已经启动并运行了它,但是端点路径实际上应该是
/containers/json
,而不是/docker/containers/json
。如果您想对您的答案进行修改,我很乐意将其标记为已接受。@J.Munson Noted and edited,谢谢您的更正。我很高兴听到它现在对你起作用了!我的下一个问题是。。。如何让docker引擎推送更新,而不需要不断轮询docker以了解应用程序的状态。有两个项目似乎解决了这个问题,但我不知道他们是如何完成的。也许是终点?您可以从中流式传输事件,并且可以使用docker events
对其进行测试。
$ curl --unix-socket /var/run/docker.sock http://containers/json