如何使用 unix 套接字从容器内部与 docker 守护程序通信?
How do I communicate with the docker daemon from inside a container using unix sockets?
一些背景知识,我有一个基于 docker-compose 的具有多个服务的应用程序。每个服务可能有 n 个实例。我的服务间通信策略要求 Redis 服务了解应用程序的当前状态,包括何时添加新实例以及何时死亡或删除实例。
通过阅读多篇博客文章和堆栈溢出问题,我知道解决方案涉及通过将 unix 套接字 /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'
}
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 端点 (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
一些背景知识,我有一个基于 docker-compose 的具有多个服务的应用程序。每个服务可能有 n 个实例。我的服务间通信策略要求 Redis 服务了解应用程序的当前状态,包括何时添加新实例以及何时死亡或删除实例。
通过阅读多篇博客文章和堆栈溢出问题,我知道解决方案涉及通过将 unix 套接字 /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'
}
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 端点 (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