关键在于构建可重复、强隔离、零残留、闭环验证的测试流水线:用专用docker-compose.test.yml定义服务与健康检查,ci中通过up--wait拉起、docker run复用网络执行测试、down-v强制清理。

用 Docker Compose 实现全自动化端到端微服务集成测试环境拉起,关键不是“启动几个容器”,而是构建一个可重复、强隔离、零残留、能闭环验证的测试流水线。核心思路是:把环境定义为代码、生命周期交由 CI 控制、测试执行与服务拓扑解耦。
写专用的 docker-compose.test.yml
不复用开发或生产配置。新建独立文件,只保留测试必需的服务(如 api、auth、db、cache),并显式约束行为:
- 用 version: "3.8" 或更高,确保健康检查、
--wait等特性可用 - 每个服务设 restart: "no",防止测试中途重启干扰状态
- 用
depends_on: [db]+healthcheck(例如 MySQL 的mysqladmin ping)确保依赖就绪再启动上层服务 - 所有卷声明为
driver_opts: {type: tmpfs}或命名卷 +tmpfs驱动,避免数据跨轮次残留 - 定义私有网络(如
testnet),让服务间通过http://api:8000这类地址通信,不暴露宿主机端口
在 CI 中原子化控制启停与测试执行
整个流程必须三步闭环,且清理动作不可跳过:
-
拉起环境:运行
docker compose -p ci-${{ RUN_ID }} -f docker-compose.test.yml up -d --wait。其中-p指定唯一 project name,保证多流水线并行不冲突;--wait等待所有健康检查通过才返回 -
执行测试:启动一个临时测试容器,复用同一网络,例如:
docker run --rm --network ci-${{ RUN_ID }}_testnet -v $(pwd)/test-results:/report tester-image pytest tests/e2e/ --junitxml=/report/junit.xml
这样测试容器能直连api、db等服务名,无需 host 映射或硬编码 IP -
强制清理:无论测试成功或失败,都执行
docker compose -p ci-${{ RUN_ID }} -f docker-compose.test.yml down -v --rmi local,删掉容器、网络、tmpfs 卷和本次构建的本地镜像
让测试容器自带执行逻辑和报告能力
不要在 CI 脚本里拼接一堆 curl 或 sleep。把测试框架、用例、配置打进专用镜像:
- Dockerfile.test 中
COPY tests/ ./tests/、COPY config.test.yaml ./ - 用
pip install -r requirements-test.txt锁定 pytest、requests、allure-pytest 等版本 - 设
ENTRYPOINT ["pytest", "-v", "--alluredir=./allure-results", "--junitxml=./junit.xml"],容器一启就跑完全部用例 - 挂载
-v $(pwd)/test-results:/app/test-results,让报告自动落盘供 CI 后续归档或解析
验证是否真正端到端隔离
环境看似跑起来了,不代表测试可信。快速自查这几个点:
- 测试容器内执行
curl -s http://host.docker.internal:3000应失败(除非 CI 显式开启 host 网络),说明没意外访问到宿主机服务 - 两个 PR 同时触发 CI,各自
docker ps查看容器名,应以不同ci-xxx_开头,网络名也互不干扰 - 数据库服务重启后,应用日志中不应出现连接拒绝(Connection refused)重试,而应等健康检查通过后才发起首次请求
- 执行完
down -v后,docker volume ls和docker network ls中不应残留任何与ci-相关的条目











