我有一个带有几个容器的docker compose堆栈。这两个问题是一个扩展的python:3-onbuild
容器(参见基本图像here),其中运行了一个falcon webserver和一个试图向python webserver发出post请求的基本node:8.11-alpine
容器。这是我的撰写文件的简化版本:
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
我知道网络正在运行,因为如果我进入lambda容器
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
我甚至在我的api上创建了一个/status
端点,试图解决这个问题。它查询数据库中所有表的名称,因此如果数据库未准备就应该失败。但是,如果我运行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
我从here
了解了有关此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
?奇怪的。由于发现了这一点,我尝试将python webserver端口更改为80,因此我可以将axios请求发送到普通的http://app
,但这会导致ENOTFOUND
错误。
我找不到有关如何解决此问题的更多信息。一个想法来自here
问题是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' }
编辑:顺便说一句,我可以通过https将lambda容器发送到外部世界的同一个POST请求(运行与应用服务相同代码的生产服务器)
编辑:如果我按照建议here从endpointUrl中删除http://
,我会Error: Invalid protocol: app
编辑:我认为它可能与使用node-alpine基本图像的this issue相关,但更改为node:8.11
或node:carbon
会导致相同的DNS问题ENOTFOUND
app
容器内从lambda
容器中卷曲Options -MultiViews
RewriteEngine On
RewriteBase /var/www/cms/public
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA]
远远超过100秒标记......
答案 0 :(得分:0)
问题最终与我的测试运动员开玩笑,开玩笑。
Jest中的默认环境是通过jsdom的类似浏览器的环境。如果要构建节点服务,则可以使用node选项来改为使用类似节点的环境。
要解决此问题,我必须在我的jest.config.js文件中添加它:
{
// ...
testEnvironment: 'node'
// ...
}