如何在Node.js中等待Docker Compose容器就绪后执行测试?
Node.js中等待Docker Compose容器就绪的优雅方案
不用硬编码休眠时间,有几种更可靠的方式实现脚本等待容器就绪后再执行测试:
1. 利用Docker健康检查+轮询容器状态
首先在你的docker-compose.yml中为目标服务配置健康检查,让Docker自动检测服务是否就绪:
services: your-test-service: image: your-service-image healthcheck: # 示例:检查HTTP服务的健康接口 test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 3s # 每隔3秒检查一次 timeout: 3s # 超时时间 retries: 5 # 重试5次后标记为不健康
然后在Node.js脚本中轮询容器的健康状态,直到目标服务进入healthy状态:
import { execSync } from "node:child_process"; import { setTimeout } from "node:timers/promises"; async function waitForHealthyService(serviceName) { while (true) { try { // 获取健康状态的服务名称 const healthyServices = execSync( `docker compose ps --filter health=healthy --format "{{.Name}}"` ).toString().trim().split("\n"); if (healthyServices.includes(serviceName)) { break; } } catch (err) { // 忽略执行错误,继续轮询 } await setTimeout(1000); } } // 使用流程 execSync("docker compose up -d"); await waitForHealthyService("your-test-service"); // 这里开始执行集成测试
2. 直接检测服务的端口或接口
如果不想配置Docker健康检查,可以直接在Node.js中尝试连接服务端口或者调用健康接口,直到成功:
检测端口是否可连接
import { execSync } from "node:child_process"; import { createConnection } from "node:net"; import { setTimeout } from "node:timers/promises"; async function waitForPort(host, port) { while (true) { try { await new Promise((resolve, reject) => { const socket = createConnection({ host, port }, () => { socket.end(); resolve(); }); socket.on("error", reject); }); break; } catch (err) { await setTimeout(1000); } } } // 使用流程 execSync("docker compose up -d"); await waitForPort("localhost", 8080); // 启动测试
检测HTTP健康接口
async function waitForHealthEndpoint(url) { while (true) { try { const res = await fetch(url); if (res.ok) break; } catch (err) { // 忽略连接错误,继续重试 } await setTimeout(1000); } } // 使用流程 await waitForHealthEndpoint("http://localhost:8080/health");
3. 使用Docker Compose的--wait参数(推荐,需版本2.10+)
如果你的Docker Compose版本在2.10及以上,可以直接使用--wait参数,这个命令会自动阻塞直到所有服务进入健康状态,无需额外编写轮询逻辑:
import { execSync } from "node:child_process"; // 执行后会一直阻塞,直到所有服务就绪 execSync("docker compose up -d --wait"); // 直接开始测试
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

