【发布时间】:2018-05-12 01:49:03
【问题描述】:
我有一个带有几个容器的 docker compose 堆栈。有问题的两个是一个扩展的python:3-onbuild 容器(参见基本图像here),其中运行着一个 falcon 网络服务器和一个基本的node:8.11-alpine 容器,它试图向 python 网络服务器发出 post 请求。 python 网络服务器正在对postgres:alpine 容器进行数据库调用。这是我的docker-compose.yml 文件的简化版本:
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
db: # postgres:alpine
ports:
- 5432:5432
build:
context: ../../
dockerfile: infra/docker/db.Dockerfile
我有一套我想要通过的集成测试。当我使用外部世界的端点运行测试时(https python 服务器运行与app 服务相同的代码),所有测试都通过了。当我尝试从我的docker-compose 堆栈内(特别是从lambda 服务到app 服务)对app 服务发出这些请求时,就会出现问题。
我认为这不是时间问题。在我的 jest 套件的 beforeAll 函数中,我轮询 python 服务器 100 秒,每 10 秒一次,如下所示:
在我的玩笑测试中
beforeAll(async () => {
const endpointUrl = getEndpointUrl();
const status = await checkStatus(endpointUrl, 10);
// NOTE: never reaches this line, starts tests before 5-minute timeout
console.log(`[integration.test]: status = ${status}`);
}, 5 * 60 * 1000); // 5-minute timeout for async function
checkStatus() 的定义位置
/**
* Checks the status of the backend every 10 seconds, n times
* @param {string} endpointUrl
* @param {number} n
*/
export function checkStatus(endpointUrl: string, n: number): Promise<string> {
console.log(`[lib][checkStatus]: before timeout date = ${Date()}`);
return new Promise<string>((resolve, reject) => {
checkStatusHelper(endpointUrl, n, resolve, reject);
});
}
function checkStatusHelper(endpointUrl, n, resolve, reject): void {
if (n === 0) reject();
setTimeout(() => {
console.log(`[lib][checkStatus]: after timeout date ${n} = ${Date()}`);
rp.get(`${endpointUrl}/status`)
.then(res => {
console.log(`[lib][checkStatus]: after request date = ${Date()}`);
console.log(`[lib][checkStatus]: res = ${res}`);
resolve('success');
})
.catch(err => {
console.log(`[lib][checkStatus]: err = ${err}`);
checkStatusHelper(endpointUrl, n - 1, resolve, reject);
});
}, 10 * 1000);
}
我得到如下输出(使用request-promise-native):
console.log src/lib.ts:30
[lib][checkStatus]: before timeout date = Fri May 11 2018 01:54:10 GMT+0000 (UTC)
console.log src/lib.ts:39
[lib][checkStatus]: after timeout date 10 = Fri May 11 2018 01:54:20 GMT+0000 (UTC)
console.log src/lib.ts:47
[lib][checkStatus]: err = RequestError: Error: getaddrinfo ENOTFOUND app app:5000
console.log src/lib.ts:39
[lib][checkStatus]: after timeout date 9 = Fri May 11 2018 01:54:31 GMT+0000 (UTC)
console.log src/lib.ts:47
[lib][checkStatus]: err = RequestError: Error: getaddrinfo ENOTFOUND app app:5000
# etc ...
类似的输出是axios 而不是request-promise-native
console.log src/lib.ts:30
[lib][checkStatus]: before timeout date = Fri May 11 2018 01:56:57 GMT+0000 (UTC)
console.log src/lib.ts:39
[lib][checkStatus]: after timeout date 10 = Fri May 11 2018 01:57:07 GMT+0000 (UTC)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Error: getaddrinfo ENOTFOUND app app:5000
at Object.dispatchError (/Halloo/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
at Request.client.on.err (/Halloo/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 (/Halloo/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.log src/lib.ts:47
[lib][checkStatus]: err = Error: Network Error
console.log src/lib.ts:39
[lib][checkStatus]: after timeout date 9 = Fri May 11 2018 01:57:18 GMT+0000 (UTC)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Error: getaddrinfo ENOTFOUND app app:5000
at Object.dispatchError (/Halloo/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
at Request.client.on.err (/Halloo/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 (/Halloo/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.log src/lib.ts:47
[lib][checkStatus]: err = Error: Network Error
# etc ...
我也不认为这不是网络问题。如果我注释掉我的测试步骤并让lambda 服务正常启动,我可以通过 ssh 进入 lambda 容器并使用axios 或request-promise-native 测试连接。这个/status 端点只返回我数据库中的所有表名,以确保数据库容器也正常运行。这几乎可以立即生效,而且远远早于 100 秒
$ node
> const axios = require('axios')
undefined
> axios.get('http://app:5000/status').then(res => console.log(res.data));
Promise {
<pending>,
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } }
> [ [ 'table0' ],
[ 'table1' ],
[ 'table2' ],
[ 'table3' ],
[ 'table4' ],
[ 'table5' ] ]
我想也许我不能将 jest 用于这些目的,但我觉得我可以,因为当我将 url 更改为在 aws 中运行的生产 https 端点并注释掉我的 jest 中的 beforeAll() 步骤时,一切正常套房。
【问题讨论】:
标签: http docker docker-compose axios jestjs