Немного предыстории: у меня есть приложение на основе docker-compose с несколькими сервисами. Каждая служба может иметь n экземпляров. Моя стратегия взаимодействия между службами требует, чтобы служба Redis знала о текущем состоянии приложения с точки зрения того, когда добавляются новые экземпляры, а когда экземпляры умирают или удаляются.
Из чтения нескольких сообщений в блогах и вопросов о переполнении стека я знаю, что решение включает в себя связь с хост-демоном докера путем привязки сокета unix /var/run/docker.sock к сокету в контейнере, но я не могу получить какую-либо поддержку. Большинство ресурсов, с которыми я сталкивался, дают довольно поверхностное объяснение того, что происходит, и там определенно не хватает какого-либо руководства по ELI5.
В настоящее время в моем docker-compose.yml у меня есть следующая конфигурация как часть одной из моих служб на основе nodejs (нет, это не часть службы Redis, потому что я сейчас нахожусь на стадии проверки концепции)...
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Я видел этот точный фрагмент десятки раз в других сообщениях и вопросах о переполнении стека, но объяснения обычно на этом заканчиваются.
В моем сервисе 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.info ошибка, я получаю вывод ниже...
{
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'
}





С API демона Docker можно обмениваться данными, используя конечные точки 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
Чтобы решить вашу проблему, вы должны запросить действительную конечную точку API Docker Engine (документация для v1.39) в качестве пути HTTP. Пример списка контейнеров:
await got('unix:/var/run/docker.sock:/containers/json')
Если у вас есть curl под рукой, вы можете проверить это из своей оболочки:
$ curl --unix-socket /var/run/docker.sock http://containers/json
@ J.Munson Замечено и отредактировано, спасибо за исправление. Я рад слышать, что это работает для вас сейчас!
Мой следующий вопрос: как заставить движок докера отправлять обновления, а не постоянно опрашивать докер на предмет состояния приложения. Есть два проекта, которые решили эту проблему, nginx-прокси и траефик, но я понятия не имею, как они справляются с этим.
Возможно, конечная точка Системные события? Вы можете транслировать события из него, и его можно протестировать с помощью docker events.
спасибо за объяснение и ссылку на документацию. Я такого раньше не встречал. Сейчас я его запустил, но на самом деле путь к конечной точке должен быть
/containers/json, а не/docker/containers/json. Если вы хотите внести поправку в свой ответ, я буду рад отметить его как принятый.