Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Docker-based test environment management for isolated, reproducible test execution. Create Docker Compose environments, manage test containers, configure service dependencies, and integrate with CI/CD pipelines.
.claude/skills/a5c-ai-docker-test-environments/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 100% | 22 |
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 95% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 63% | 0% |
You are docker-test-environments - a specialized skill for Docker-based test environment management, providing isolated, reproducible test execution capabilities.
This skill enables AI-powered test environment management including:
Create isolated test environments with Docker Compose:
yaml# 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
bash# Start test environment docker compose -f docker-compose.test.yml up -d # Wait for services to be healthy docker compose -f docker-compose.test.yml up -d --wait # Run tests against environment docker compose -f docker-compose.test.yml exec app npm test # View logs docker compose -f docker-compose.test.yml logs -f # Stop and cleanup docker compose -f docker-compose.test.yml down -v --remove-orphans
Use Testcontainers for programmatic container management:
javascript// JavaScript/TypeScript with Testcontainers import { PostgreSqlContainer } from '@testcontainers/postgresql'; import { RedisContainer } from '@testcontainers/redis'; describe('Integration Tests', () => { let postgresContainer; let redisContainer; beforeAll(async () => { // Start PostgreSQL postgresContainer = await new PostgreSqlContainer('postgres:15') .withDatabase('testdb') .withUsername('test') .withPassword('test') .start(); // Start Redis redisContainer = await new RedisContainer('redis:7') .start(); // Set environment variables process.env.DATABASE_URL = postgresContainer.getConnectionUri(); process.env.REDIS_URL = redisContainer.getConnectionUrl(); }, 60000); afterAll(async () => { await postgresContainer?.stop(); await redisContainer?.stop(); }); it('should connect to database', async () => { // Test implementation }); });
python# 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() # Test implementation
Configure robust health checks:
yamlservices: 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
Seed test data automatically:
bash# SQL initialization cat > test-data/init.sql << 'EOF' -- Create test schema CREATE SCHEMA IF NOT EXISTS test; -- Create tables 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 test data INSERT INTO test.users (email, name) VALUES ('test1@example.com', 'Test User 1'), ('test2@example.com', 'Test User 2'); EOF
yaml# Mount initialization scripts 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
Configure isolated test networks:
yaml# Multiple isolated test environments 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 # Shared service mock-server: networks: - external-network
yaml# GitHub Actions example name: Integration Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Start test environment run: | docker compose -f docker-compose.test.yml up -d --wait docker compose -f docker-compose.test.yml ps - name: Run tests run: | docker compose -f docker-compose.test.yml exec -T app npm test - name: Collect logs on failure if: failure() run: | docker compose -f docker-compose.test.yml logs > test-logs.txt - name: Upload logs if: failure() uses: actions/upload-artifact@v4 with: name: test-logs path: test-logs.txt - name: Cleanup if: always() run: | docker compose -f docker-compose.test.yml down -v --remove-orphans
yamlpostgres: 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
yamlmysql: 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
yamlmongo: 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
yamlredis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5
yamlelasticsearch: 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
yamlkafka: 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
This skill can leverage the following MCP servers for enhanced capabilities:
| Server | Description | Installation | |--------|-------------|--------------| | QuantGeekDev/docker-mcp | Docker container management | GitHub | | Docker MCP Toolkit | Official Docker MCP | Docker Blog | | Docker Hub MCP | Docker Hub integration | Docker |
latest for reproducibility-v flag--wait or health checks before testsThis skill integrates with the following processes:
environment-management.js - All phases of environment setuptest-data-management.js - Data seeding and cleanupautomation-framework.js - Test framework environment setupcontinuous-testing.js - CI/CD environment managementWhen executing operations, provide structured output:
json{ "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" } }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 13,138 | 12,224 | -7% | 1 | 1 | 0% | 2,881 | 5,631 | +95% | 0 | 0 | — |
case-02 | fail→pass | 18,285 | 11,447 | -37% | 1 | 1 | 0% | 3,431 | 5,545 | +62% | 0 | 0 | — |
case-03 | fail→pass | 20,213 | 15,162 | -25% | 1 | 1 | 0% | 4,646 | 6,527 | +40% | 0 | 0 | — |
case-04 | fail→pass | 17,033 | 18,953 | +11% | 1 | 1 | 0% | 2,911 | 6,906 | +137% | 0 | 0 | — |
case-05 | pass→fail | 34,810 | 24,701 | -29% | 1 | 1 | 0% | 8,157 | 7,575 | -7% | 0 | 0 | — |
case-06 | pass→pass | 14,952 | 14,540 | -3% | 1 | 1 | 0% | 2,846 | 6,435 | +126% | 0 | 0 | — |
case-07 | pass→pass | 9,752 | 11,771 | +21% | 1 | 1 | 0% | 1,878 | 5,518 | +194% | 0 | 0 | — |
case-08 | pass→pass | 7,249 | 8,557 | +18% | 1 | 1 | 0% | 1,388 | 4,678 | +237% | 0 | 0 | — |
case-09 | pass→pass | 4,087 | 6,255 | +53% | 1 | 1 | 0% | 739 | 4,270 | +478% | 0 | 0 | — |
case-10 | pass→pass | 10,488 | 10,551 | +1% | 1 | 1 | 0% | 1,863 | 4,853 | +160% | 0 | 0 | — |
case-11 | pass→pass | 5,944 | 7,348 | +24% | 1 | 1 | 0% | 1,170 | 4,568 | +290% | 0 | 0 | — |
case-12 | pass→pass | 7,112 | 9,620 | +35% | 1 | 1 | 0% | 1,406 | 5,000 | +256% | 0 | 0 | — |
case-13 | pass→pass | 11,051 | 14,988 | +36% | 1 | 1 | 0% | 2,047 | 5,581 | +173% | 0 | 0 | — |
case-14 | pass→pass | 5,326 | 5,487 | +3% | 1 | 1 | 0% | 941 | 3,948 | +320% | 0 | 0 | — |
case-15 | pass→pass | 2,497 | 4,621 | +85% | 1 | 1 | 0% | 390 | 3,808 | +876% | 0 | 0 | — |
case-16 | pass→pass | 3,294 | 4,456 | +35% | 1 | 1 | 0% | 537 | 3,864 | +620% | 0 | 0 | — |
case-17 | pass→pass | 3,903 | 6,152 | +58% | 1 | 1 | 0% | 647 | 4,118 | +536% | 0 | 0 | — |
case-18 | pass→pass | 16,585 | 15,148 | -9% | 1 | 1 | 0% | 3,089 | 6,040 | +96% | 0 | 0 | — |
case-19 | fail→pass | 20,205 | 7,459 | -63% | 1 | 1 | 0% | 2,808 | 4,588 | +63% | 0 | 0 | — |
case-20 | pass→pass | 12,946 | 12,120 | -6% | 1 | 1 | 0% | 2,264 | 5,268 | +133% | 0 | 0 | — |
case-21 | pass→pass | 5,482 | 5,714 | +4% | 1 | 1 | 0% | 982 | 4,200 | +328% | 0 | 0 | — |
case-22 | pass→pass | 7,401 | 7,137 | -4% | 1 | 1 | 0% | 1,424 | 4,490 | +215% | 0 | 0 | — |
case-23 | pass→pass | 6,465 | 3,753 | -42% | 1 | 1 | 0% | 1,067 | 3,779 | +254% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.