У меня есть стек для создания докеров с несколькими контейнерами. Эти два вопроса представляют собой расширенный контейнер python:3-onbuild
(см. Базовое изображение здесь ) с запущенным веб-сервером falcon и базовый контейнер node:8.11-alpine
, который пытается отправлять запросы на веб-сервер python. Это упрощенная версия моего составного файла:
version: '3.6'
services:
app: # python:3-onbuild
ports:
- 5000
build:
context: ../../
dockerfile: infra/docker/app.Dockerfile
lambda: # node:8.11-alpine
ports:
- 10000
build:
context: ../../
dockerfile: infra/docker/lambda.Dockerfile
depends_on:
- app
Я знаю, что сеть работает, потому что если я ssh в лямбда-контейнер
docker exec -it default_lambda_1 /bin/ash
и запустите ping app
Я получу ответ.
$ ping app
PING app (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.184 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.141 ms
Я могу даже бежать ping app:5000
ping app:5000
PING app:5000 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.105 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.176 ms
Я даже создал конечную точку /status
на своем API, чтобы попытаться решить эту проблему. Он запрашивает имена всех таблиц в базе данных, поэтому он должен потерпеть неудачу, если база данных не готова. Но, если я запускаю curl http://app:5000/status
, я получаю ответ со всеми именами таблиц, никаких проблем вообще.
Проблема возникает только тогда, когда процесс моего узла пытается сделать пост-запрос (используя axios)
this.endpointUrl = 'http://app:5000';
const options: AxiosRequestConfig = {
method: 'POST',
url: `${this.endpointUrl}/session/get`,
data: {
'client': 'alexa'
},
responseType: 'json'
};
axios(options)
.then((response: AxiosResponse<any>) => {
console.log(`[SessionService][getSession]: "/session/get" responseData = ${JSON.stringify(response.data)}`);
})
.catch(err => {
console.error(`[SessionService][getSession]: error = ${err}`);
});
Я получаю следующую ошибку:
console.error src/index.ts:111
VirtualConsole.on.e at project/node_modules/jsdom/lib/jsdom/virtual-console.js:29:45
Error: Error: getaddrinfo ENOTFOUND app app:5000
at Object.dispatchError (/project/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
at Request.client.on.err (/project/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
at emitOne (events.js:121:20)
at Request.emit (events.js:211:7)
at Request.onRequestError (/project/node_modules/request/request.js:878:8)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at Socket.socketErrorListener (_http_client.js:387:9)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7) undefined
console.error src/index.ts:111
axios_1.default.then.catch.err at services/Service.ts:94:25
[SessionService][getSession]: error = Error: Network Error
Я узнал больше об этом ENOTFOUND
сообщении об ошибке здесь
getaddrinfo по определению является проблемой DNS
Итак, я изучил использование узла dns
packge для поиска app
> dns.lookup('app', console.log)
GetAddrInfoReqWrap {
callback: [Function: bound consoleCall],
family: 0,
hostname: 'app',
oncomplete: [Function: onlookup],
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } }
> null '172.18.0.3' 4
> dns.lookup('app:5000', console.log)
GetAddrInfoReqWrap {
callback: [Function: bound consoleCall],
family: 0,
hostname: 'app:5000',
oncomplete: [Function: onlookup],
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } }
> { Error: getaddrinfo ENOTFOUND app:5000
at errnoException (dns.js:50:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'app:5000' }
Похоже, он может найти app
, но не app:5000
? Weird. С тех пор как я это выяснил, я попытался изменить порт веб-сервера python на 80, чтобы я мог сделать запросы axios равными ol 10 *, но это привело к той же самой ошибке ENOTFOUND
.
Я не могу найти много информации о том, как это исправить. Одна идея от здесь
проблема в том, что http.request использует dns.lookup вместо dns.resolve
Ответ предлагает использовать оверлейную сеть. Я не очень понимаю, что это такое, но если это потребуется, я сделаю это. Но мне интересно, есть ли более простое решение сейчас, когда я использую compose yml версии 3.6. В любом случае, dns.resolve
дает мне вывод, аналогичный dns.lookup
> dns.resolve('app', console.log)
QueryReqWrap {
bindingName: 'queryA',
callback: [Function: bound consoleCall],
hostname: 'app',
oncomplete: [Function: onresolve],
ttl: false,
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
channel: ChannelWrap {} }
> null [ '172.18.0.3' ]
> dns.resolve('app:5000', console.log)
QueryReqWrap {
bindingName: 'queryA',
callback: [Function: bound consoleCall],
hostname: 'app:5000',
oncomplete: [Function: onresolve],
ttl: false,
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
channel: ChannelWrap {} }
> { Error: queryA ENOTFOUND app:5000
at errnoException (dns.js:50:10)
at QueryReqWrap.onresolve [as oncomplete] (dns.js:238:19)
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
syscall: 'queryA',
hostname: 'app:5000' }
РЕДАКТИРОВАТЬ: Кстати, я могу сделать те же POST-запросы из лямбда-контейнера через https во внешний мир (рабочий сервер работает с тем же кодом, что и служба приложения)
EDIT: если я удаляю http://
из endpointUrl, как предложено здесь , я получаю Error: Invalid protocol: app
РЕДАКТИРОВАТЬ: я думал, что это может быть связано с этой проблемой с базовым образом узла-альпийского, но изменение на node:8.11
или node:carbon
привело к той же проблеме DNS ENOTFOUND
РЕДАКТИРОВАТЬ: Я уверен, что это не проблема синхронизации, потому что я жду, чтобы запустить мои тесты в течение 100 секунд, делая тестовый запрос каждые 10 секунд. Если я пропущу шаг теста и позволю контейнеру вращаться как обычно, я смогу свернуться app
из контейнера lambda
задолго до 100-секундной отметки ...