Starts arbitrary Docker containers using Testcontainers based on declarative configuration. See useGenericContainer.md for extended guide; this file summarizes core hook behavior.
Start arbitrary Docker containers via declarative configuration for integration tests that require real external dependencies (databases, caches, message brokers). Provides simple setup and automatic lifecycle management.
- Declarative multi-container configuration
- Automatic port mapping and host access
- Environment variables, commands, labels, platform, reuse
- Optional log forwarding to framework logger
- Automatic start before tests and stop after tests
useGenericContainer({
containers: {
redis: {image: "redis:7-alpine", exposedPorts: [6379]},
postgres: {image: "postgres:15-alpine", exposedPorts: [5432], environment: {POSTGRES_PASSWORD: "pw"}},
},
});const redis = useGenericContainer("redis");
const port = redis.getPort(6379);Key fields: image, exposedPorts, environment, command, privilegedMode, labels, reuse, platform, waitForLog.
useGenericContainer({
containerLogging: true, // forward container logs
containers: {
mysql: {
image: "mysql:8",
exposedPorts: [3306],
environment: {
MYSQL_ROOT_PASSWORD: "root",
MYSQL_DATABASE: "testdb",
},
labels: {"test.suite": "integration"},
reuse: false,
platform: "linux/amd64",
waitForLog: "ready for connections",
},
},
});- Seeding Data: Connect using host/port from
getPortthen seed with client libraries. - Custom Commands: Provide
commandfor images requiring non-default process start. - Selective Reuse: Use
reuse: truefor faster local runs (be mindful of cross-test state). - Platform Pinning: Specify
platformon arm64/mac or CI runners if needed.
it("seeds redis", async () => {
const redis = useGenericContainer("redis");
const host = redis.host;
const port = redis.getPort(6379);
const {createClient} = await import("redis");
const client = createClient({url: `redis://${host}:${port}`});
await client.connect();
await client.set("k", "v");
const v = await client.get("k");
assert.strictEqual(v, "v");
await client.disconnect();
});| Hook | Pattern |
|---|---|
| RepositoryHook | Run integration tests against real DB containers. |
| PerformanceBudgetHook | Measure container startup or query latency. |
| MetricsHook | Record operation counts & timings interacting with containers. |
| EmergencyCleanup | Ensure containers stopped on unexpected failures. |
// Illustrative shape
useGenericContainer({
containerLogging: true,
containers: {
myservice: {
image: "repo/image:tag",
exposedPorts: [1234],
environment: {KEY: "VALUE"},
command: ["cmd", "--arg"],
privilegedMode: false,
labels: {key: "value"},
reuse: false,
platform: "linux/amd64",
waitForLog: "ready",
},
},
});const info = useGenericContainer("redis");
// info: { container, host, ports: Map<number, number>, getPort(original: number): number }const all = useGenericContainer.useAll(); // Map<string, ContainerInfo>- beforeStart: starts all configured containers (auto runtime detection)
- afterTests: stops containers
- Pin Versions: Avoid
latest; use explicit tags for reproducibility - Minimal Exposure: Expose only required ports
- Log Forwarding: Enable
containerLoggingwhen debugging startup issues - Avoid Reuse in CI: Prefer clean state per run for reliability
| Symptom | Cause | Resolution |
|---|---|---|
| Container fails to start | Image pull issue / bad config | Verify image, env vars; enable logging; pre-pull in CI |
| Port undefined | Port not in exposedPorts |
Add port to configuration |
| Connection refused | Container not ready | Add waitForLog or retry/backoff |
| Huge logs | containerLogging on |
Disable in stable suites |
- Docker missing: Hook will fail early; fall back to memory or skip
- Platform mismatch: Pin
platformfor arm64/mac vs amd64 images - State leakage:
reuse: truecan leak state across tests—disable for strict isolation - Network policies: Custom networks require raw variant configuration
- Detailed cookbook:
useGenericContainer.md. - Raw factory approach:
GenericContainerRawHook.md/useGenericContainerRaw.md.