name: docker-test-environments description: 基于Docker的测试环境管理,用于隔离、可重复的测试执行。创建Docker Compose环境,管理测试容器,配置服务依赖,并与CI/CD流水线集成。 allowed-tools: Bash(*) Read Write Edit Glob Grep WebFetch metadata: author: babysitter-sdk version: “1.0.0” category: environment-management backlog-id: SK-020
docker-test-environments
你是 docker-test-environments - 一个专门用于基于Docker的测试环境管理的技能,提供隔离、可重复的测试执行能力。
概述
此技能支持AI驱动的测试环境管理,包括:
- 创建Docker Compose测试环境
- 管理用于集成测试的Testcontainers
- 配置服务依赖和健康检查
- 数据库种子数据和测试数据管理
- 测试环境的网络隔离
- 环境清理自动化
- CI/CD Docker集成模式
前提条件
- Docker Engine已安装并运行
- Docker Compose v2已安装
- 足够的系统资源用于容器
- 可选:用于语言特定集成的Testcontainers库
能力
1. Docker Compose测试环境
使用Docker Compose创建隔离的测试环境:
# docker-compose.test.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
- NODE_ENV=test
- DATABASE_URL=postgres://test:test@db:5432/testdb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- test-network
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=test
- POSTGRES_PASSWORD=test
- POSTGRES_DB=testdb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U test -d testdb"]
interval: 5s
timeout: 5s
retries: 5
volumes:
- ./test-data/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- test-network
redis:
image: redis:7-alpine
networks:
- test-network
networks:
test-network:
driver: bridge
2. 环境生命周期命令
# 启动测试环境
docker compose -f docker-compose.test.yml up -d
# 等待服务健康
docker compose -f docker-compose.test.yml up -d --wait
# 针对环境运行测试
docker compose -f docker-compose.test.yml exec app npm test
# 查看日志
docker compose -f docker-compose.test.yml logs -f
# 停止并清理
docker compose -f docker-compose.test.yml down -v --remove-orphans
3. Testcontainers集成
使用Testcontainers进行编程式容器管理:
// JavaScript/TypeScript with Testcontainers
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { RedisContainer } from '@testcontainers/redis';
describe('集成测试', () => {
let postgresContainer;
let redisContainer;
beforeAll(async () => {
// 启动PostgreSQL
postgresContainer = await new PostgreSqlContainer('postgres:15')
.withDatabase('testdb')
.withUsername('test')
.withPassword('test')
.start();
// 启动Redis
redisContainer = await new RedisContainer('redis:7')
.start();
// 设置环境变量
process.env.DATABASE_URL = postgresContainer.getConnectionUri();
process.env.REDIS_URL = redisContainer.getConnectionUrl();
}, 60000);
afterAll(async () => {
await postgresContainer?.stop();
await redisContainer?.stop();
});
it('应该连接到数据库', async () => {
// 测试实现
});
});
# Python with Testcontainers
import pytest
from testcontainers.postgres import PostgresContainer
from testcontainers.redis import RedisContainer
@pytest.fixture(scope="session")
def postgres_container():
with PostgresContainer("postgres:15") as postgres:
yield postgres
@pytest.fixture(scope="session")
def redis_container():
with RedisContainer("redis:7") as redis:
yield redis
def test_database_connection(postgres_container):
connection_url = postgres_container.get_connection_url()
# 测试实现
4. 健康检查模式
配置健壮的健康检查:
services:
api:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
elasticsearch:
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q 'green\\|yellow'"]
interval: 10s
timeout: 10s
retries: 10
start_period: 60s
kafka:
healthcheck:
test: ["CMD-SHELL", "kafka-topics.sh --bootstrap-server localhost:9092 --list"]
interval: 10s
timeout: 10s
retries: 5
5. 数据库种子数据
自动种子测试数据:
# SQL初始化
cat > test-data/init.sql << 'EOF'
-- 创建测试模式
CREATE SCHEMA IF NOT EXISTS test;
-- 创建表
CREATE TABLE test.users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入测试数据
INSERT INTO test.users (email, name) VALUES
('test1@example.com', '测试用户 1'),
('test2@example.com', '测试用户 2');
EOF
# 挂载初始化脚本
services:
db:
volumes:
- ./test-data/init.sql:/docker-entrypoint-initdb.d/01-init.sql
- ./test-data/seed.sql:/docker-entrypoint-initdb.d/02-seed.sql
6. 网络隔离
配置隔离的测试网络:
# 多个隔离的测试环境
networks:
test-network-a:
driver: bridge
internal: true
test-network-b:
driver: bridge
internal: true
external-network:
driver: bridge
services:
app-a:
networks:
- test-network-a
- external-network
app-b:
networks:
- test-network-b
- external-network
# 共享服务
mock-server:
networks:
- external-network
7. CI/CD集成
# GitHub Actions示例
name: 集成测试
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 启动测试环境
run: |
docker compose -f docker-compose.test.yml up -d --wait
docker compose -f docker-compose.test.yml ps
- name: 运行测试
run: |
docker compose -f docker-compose.test.yml exec -T app npm test
- name: 失败时收集日志
if: failure()
run: |
docker compose -f docker-compose.test.yml logs > test-logs.txt
- name: 上传日志
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-logs
path: test-logs.txt
- name: 清理
if: always()
run: |
docker compose -f docker-compose.test.yml down -v --remove-orphans
常见服务模板
PostgreSQL
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U test"]
interval: 5s
timeout: 5s
retries: 5
MySQL
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 5
MongoDB
mongo:
image: mongo:6
environment:
MONGO_INITDB_ROOT_USERNAME: test
MONGO_INITDB_ROOT_PASSWORD: test
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
interval: 10s
timeout: 10s
retries: 5
Redis
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
Elasticsearch
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200 | grep -q 'cluster_name'"]
interval: 10s
timeout: 10s
retries: 10
Kafka
kafka:
image: confluentinc/cp-kafka:7.5.0
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
depends_on:
- zookeeper
MCP服务器集成
此技能可以利用以下MCP服务器增强能力:
| 服务器 | 描述 | 安装 |
|---|---|---|
| QuantGeekDev/docker-mcp | Docker容器管理 | GitHub |
| Docker MCP Toolkit | 官方Docker MCP | Docker博客 |
| Docker Hub MCP | Docker Hub集成 | Docker |
最佳实践
- 使用特定镜像标签 - 避免使用
latest以保证可重复性 - 健康检查 - 始终为依赖项配置健康检查
- 资源限制 - 为容器设置内存/CPU限制
- 清理 - 始终使用
-v标志清理卷 - 等待就绪 - 在测试前使用
--wait或健康检查 - 隔离 - 为测试环境使用专用网络
- 临时数据 - 切勿挂载生产数据卷
流程集成
此技能与以下流程集成:
environment-management.js- 环境设置的所有阶段test-data-management.js- 数据种子和清理automation-framework.js- 测试框架环境设置continuous-testing.js- CI/CD环境管理
输出格式
执行操作时,提供结构化输出:
{
"operation": "start-environment",
"composeFile": "docker-compose.test.yml",
"status": "running",
"services": {
"app": { "status": "running", "health": "healthy" },
"db": { "status": "running", "health": "healthy" },
"redis": { "status": "running", "health": "healthy" }
},
"network": "test-network",
"connectionStrings": {
"database": "postgres://test:test@localhost:5432/testdb",
"redis": "redis://localhost:6379"
}
}
错误处理
- 检查Docker守护进程连接
- 启动前验证镜像可用性
- 优雅处理容器启动失败
- 失败时提供诊断日志
- 为不稳定的容器实现重试逻辑
约束
- 不要在测试环境中暴露生产数据
- 限制资源消耗以防止系统问题
- 测试后始终清理环境
- 为并行测试使用适当的隔离
- 尊重端口分配以避免冲突