13.1.2.3 CI Test Databases
A focused guide to CI Test Databases, connecting core concepts with practical Docker and container operations.
CI test databases are containerized database instances provided specifically for a CI pipeline's integration tests, freshly created for each test run, ensuring tests start from a clean, predictable state without depending on or potentially interfering with any shared, persistent database.
Providing a Fresh Database for Each CI Run
A CI-specific Compose file brings up a database container freshly for each pipeline run, with no expectation of data persisting between runs.
services:
test-db:
image: postgres:16
environment:
- POSTGRES_DB=test_db
- POSTGRES_PASSWORD=test
Without a declared volume, this database's data exists only for the duration of this specific container's life, naturally discarded once the CI run completes.
Why Starting Fresh Each Time Is Important for Test Reliability
A test database carrying over data from a previous run risks one run's leftover data affecting a subsequent run's test results, an unreliable, hard-to-reproduce source of test failures that starting fresh each time avoids entirely.
docker compose -f docker-compose.test.yml up -d test-db
docker compose -f docker-compose.test.yml run --rm app npm run test:integration
docker compose -f docker-compose.test.yml down -v
The final teardown, including volume removal, ensures the next CI run starts from an equally fresh state.
Seeding the Test Database With Known, Predictable Data
Running a seed script as part of database initialization provides integration tests with predictable, known starting data to test against.
services:
test-db:
image: postgres:16
volumes:
- ./test/seed:/docker-entrypoint-initdb.d
Running Database Migrations Before Tests Execute
For an application using a migration-based schema, running migrations against the fresh test database before tests actually run ensures the schema matches what the application expects.
docker compose -f docker-compose.test.yml run --rm app npm run migrate
Why CI Test Databases Matter
Providing a freshly created, predictably seeded database specifically for each CI run is essential for reliable, reproducible integration test results, avoiding the kind of test pollution and unpredictability a shared or persistent database could otherwise introduce.