Skip to content

Commit 212ccdc

Browse files
Doc improvements
1 parent 0c3d4e4 commit 212ccdc

File tree

10 files changed

+122
-171
lines changed

10 files changed

+122
-171
lines changed

docs/configuration.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ Configuration of the Docker daemon:
3333
Configuration of Testcontainers and its behaviours:
3434

3535
| Variable | Example | Description |
36-
| ------------------------------------- | -------------------------- | -------------------------------------------- |
36+
| ------------------------------------- |----------------------------| -------------------------------------------- |
3737
| TESTCONTAINERS_HOST_OVERRIDE | tcp://docker:2375 | Docker's host on which ports are exposed |
3838
| TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE | /var/run/docker.sock | Path to Docker's socket used by ryuk |
3939
| TESTCONTAINERS_RYUK_PRIVILEGED | true | Run ryuk as a privileged container |
4040
| TESTCONTAINERS_RYUK_DISABLED | true | Disable ryuk |
4141
| TESTCONTAINERS_RYUK_PORT | 65515 | Set ryuk host port (not recommended) |
4242
| TESTCONTAINERS_SSHD_PORT | 65515 | Set SSHd host port (not recommended) |
4343
| TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX | mycompany.com/registry | Set default image registry |
44-
| RYUK_CONTAINER_IMAGE | testcontainers/ryuk:0.11.0 | Custom image for ryuk |
45-
| SSHD_CONTAINER_IMAGE | testcontainers/sshd:1.1.0 | Custom image for SSHd |
44+
| RYUK_CONTAINER_IMAGE | testcontainers/ryuk:0.12.0 | Custom image for ryuk |
45+
| SSHD_CONTAINER_IMAGE | testcontainers/sshd:1.3.0 | Custom image for SSHd |
4646
| TESTCONTAINERS_REUSE_ENABLE | true | Enable reusable containers |
4747
| TESTCONTAINERS_RYUK_VERBOSE | true | Sets RYUK_VERBOSE env var in ryuk container |

docs/features/advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Container Runtime Client
44

5-
Testcontainers configures an underlying container runtime to perform its tasks. This runtime works automatically with several providers like Docker, Podman, Colima, Rancher Desktop and Testcontainers Desktop. There are too many usage examples to list here, but here are some common examples:
5+
Testcontainers configures an underlying container runtime to perform its tasks. This runtime works automatically with several providers like Docker, Podman, Colima, Rancher Desktop and Testcontainers Desktop. There are too many usage examples to list here, but here are some common examples.
66

77
### Fetch container runtime information
88

docs/quickstart/authentication.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Authentication

docs/quickstart/global-setup.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
# Global setup
22

3-
If you have a lot of tests that require the same container, you might not want to spin up one per test.
3+
If you have many tests that require the same container, you may not want to spin up one per test.
44

5-
In this case a common pattern is to set the container up globally, and reuse it in your tests. Here's an example using Vitest:
5+
!!! info
6+
There is a misconception that containers are heavyweight.
67

7-
```ts
8-
// setup.js
8+
Sure, if your container has a slow startup time (e.g., a database, which on startup runs large migration scripts), it may be better to just start and manage one instance. But keep in mind that this limits your tests to run sequentially, and you may need to manage the state of the container between tests.
99

10-
import { createClient, RedisClientType } from "redis";
11-
import { GenericContainer, StartedTestContainer } from "testcontainers";
10+
In many cases it is far easier to start a new container for each test and run them in parallel. Of course, this depends on your specific use case.
11+
12+
Many popular test frameworks like Jest and Vitest support global setup and teardown scripts.
13+
14+
---
15+
16+
Here's an example which sets up a single Redis container globally, so it can be reused across tests. In this case we're using Vitest:
17+
18+
```ts title="setup.js" linenums="1"
19+
import { createClient } from "redis";
20+
import { RedisContainer } from "testcontainers";
1221

1322
export async function setup() {
14-
globalThis.redisContainer = await new GenericContainer("redis")
15-
.withExposedPorts(6379)
16-
.start();
23+
const container = await new RedisContainer("redis:8").start();
24+
const client = createClient({ url: container.getConnectionUrl() });
25+
await client.connect();
1726

18-
globalThis.redisClient = createClient({
19-
url: `redis://${redisContainer.getHost()}:${redisContainer.getMappedPort(6379)}`
20-
});
21-
22-
await globalThis.redisClient.connect();
27+
globalThis.redisContainer = container;
28+
globalThis.redisClient = client;
2329
}
2430

2531
export async function teardown() {
@@ -28,9 +34,7 @@ export async function teardown() {
2834
}
2935
```
3036

31-
```ts
32-
// vite.config.js
33-
37+
```ts title="vite.config.js" linenums="1"
3438
import { defineConfig } from "vite";
3539

3640
export default defineConfig({
@@ -40,13 +44,9 @@ export default defineConfig({
4044
});
4145
```
4246

43-
And to reference the container/client in your tests:
47+
And to use the container/client in your tests:
4448

45-
```ts
46-
it("should set and retrieve a value from Redis", async () => {
47-
await globalThis.redisClient.set("key", "test-value");
48-
const result = await globalThis.redisClient.get("key");
49-
50-
expect(result).toBe("test-value");
51-
});
49+
```ts linenums="1"
50+
await globalThis.redisClient.set("key", "test-value");
51+
const result = await globalThis.redisClient.get("key");
5252
```

docs/quickstart/install.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Install
22

3-
Install the Testcontainers dependency.
4-
53
## NPM
64

75
```bash

docs/quickstart/logging.md

Lines changed: 18 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,24 @@
11
# Logging
22

3-
It would be nice to see what Testcontainers is doing while the test is running. You can enable all logs by setting the `DEBUG` environment variable. For example:
3+
Testcontainers writes logs using the [debug](https://www.npmjs.com/package/debug) library. This allows you to enable or disable logs at runtime, and to filter logs by namespace.
44

5-
```bash
6-
DEBUG=testcontainers* npm test
7-
```
5+
The following namespaces are available:
86

9-
If we run the test again, we'll see a lot of debug output:
7+
- `testcontainers*`: Show all logs
8+
- `testcontainers`: Show Testcontainers core logs
9+
- `testcontainers:containers`: Show logs from containers
10+
- `testcontainers:compose`: Show logs from Docker Compose
11+
- `testcontainers:build`: Show build logs
12+
- `testcontainers:pull`: Show image pull logs
13+
- `testcontainers:exec`: Show container execution logs
1014

11-
```
12-
[DEBUG] Checking container runtime strategy "UnixSocketStrategy"...
13-
[TRACE] Fetching Docker info...
14-
[TRACE] Fetching remote container runtime socket path...
15-
[TRACE] Resolving host...
16-
[TRACE] Fetching Compose info...
17-
[TRACE] Looking up host IPs...
18-
[TRACE] Initialising clients...
19-
[TRACE] Container runtime info:
20-
{
21-
"node": {
22-
"version": "v22.14.0",
23-
"architecture": "x64",
24-
"platform": "linux"
25-
},
26-
"containerRuntime": {
27-
"host": "localhost",
28-
"hostIps": [
29-
{
30-
"address": "127.0.0.1",
31-
"family": 4
32-
}
33-
],
34-
"remoteSocketPath": "/var/run/docker.sock",
35-
"indexServerAddress": "https://index.docker.io/v1/",
36-
"serverVersion": "28.0.1",
37-
"operatingSystem": "Docker Desktop",
38-
"operatingSystemType": "linux",
39-
"architecture": "x86_64",
40-
"cpus": 32,
41-
"memory": 33524871168,
42-
"runtimes": [
43-
"io.containerd.runc.v2",
44-
"nvidia",
45-
"runc"
46-
],
47-
"labels": [
48-
"com.docker.desktop.address=unix:///var/run/docker-cli.sock"
49-
]
50-
},
51-
"compose": {
52-
"version": "2.33.1-desktop.1",
53-
"compatability": "v2"
54-
}
55-
}
56-
[DEBUG] Container runtime strategy "UnixSocketStrategy" works
57-
[DEBUG] Checking if image exists "redis:latest"...
58-
[DEBUG] Checked if image exists "redis:latest"
59-
[DEBUG] Pulling image "redis:latest"...
60-
[DEBUG] Executing Docker credential provider "docker-credential-desktop.exe"
61-
[DEBUG] Auth config found for registry "https://index.docker.io/v1/": CredsStore
62-
[redis:latest] {"status":"Pulling from library/redis","id":"latest"}
63-
[redis:latest] {"status":"Pulling fs layer","progressDetail":{},"id":"6e909acdb790"}
64-
...
65-
[redis:latest] {"status":"Status: Downloaded newer image for redis:latest"}
66-
[DEBUG] Pulled image "redis:latest"
67-
[DEBUG] Acquiring lock file "/tmp/testcontainers-node.lock"...
68-
[DEBUG] Acquired lock file "/tmp/testcontainers-node.lock"
69-
[DEBUG] Listing containers...
70-
[DEBUG] Listed containers
71-
[DEBUG] Creating new Reaper for session "4c81d4efc176" with socket path "/var/run/docker.sock"...
72-
[DEBUG] Checking if image exists "testcontainers/ryuk:0.11.0"...
73-
[DEBUG] Checked if image exists "testcontainers/ryuk:0.11.0"
74-
[DEBUG] Image "testcontainers/ryuk:0.11.0" already exists
75-
[DEBUG] Creating container for image "testcontainers/ryuk:0.11.0"...
76-
[DEBUG] [11a9d12ea231] Created container for image "testcontainers/ryuk:0.11.0"
77-
[INFO] [11a9d12ea231] Starting container for image "testcontainers/ryuk:0.11.0"...
78-
[DEBUG] [11a9d12ea231] Starting container...
79-
[DEBUG] [11a9d12ea231] Started container
80-
[INFO] [11a9d12ea231] Started container for image "testcontainers/ryuk:0.11.0"
81-
[DEBUG] [11a9d12ea231] Fetching container logs...
82-
[DEBUG] [11a9d12ea231] Demuxing stream...
83-
[DEBUG] [11a9d12ea231] Demuxed stream
84-
[DEBUG] [11a9d12ea231] Fetched container logs
85-
[DEBUG] [11a9d12ea231] Waiting for container to be ready...
86-
[DEBUG] [11a9d12ea231] Waiting for log message "/.*Started.*/"...
87-
[DEBUG] [11a9d12ea231] Fetching container logs...
88-
[11a9d12ea231] time=2025-03-24T12:10:17.130Z level=INFO msg=starting connection_timeout=1m0s reconnection_timeout=10s request_timeout=10s shutdown_timeout=10m0s remove_retries=10 retry_offset=-1s changes_retry_interval=1s port=8080 verbose=false
89-
[11a9d12ea231] time=2025-03-24T12:10:17.130Z level=INFO msg=Started address=[::]:8080
90-
[11a9d12ea231] time=2025-03-24T12:10:17.130Z level=INFO msg="client processing started"
91-
[DEBUG] [11a9d12ea231] Demuxing stream...
92-
[DEBUG] [11a9d12ea231] Demuxed stream
93-
[DEBUG] [11a9d12ea231] Fetched container logs
94-
[DEBUG] [11a9d12ea231] Log wait strategy complete
95-
[INFO] [11a9d12ea231] Container is ready
96-
[DEBUG] [11a9d12ea231] Connecting to Reaper (attempt 1) on "localhost:32774"...
97-
[DEBUG] [11a9d12ea231] Connected to Reaper
98-
[DEBUG] Releasing lock file "/tmp/testcontainers-node.lock"...
99-
[DEBUG] Released lock file "/tmp/testcontainers-node.lock"
100-
[DEBUG] Creating container for image "redis:latest"...
101-
[11a9d12ea231] time=2025-03-24T12:10:17.145Z level=INFO msg="client connected" address=172.17.0.1:40446 clients=1
102-
[11a9d12ea231] time=2025-03-24T12:10:17.145Z level=INFO msg="adding filter" type=label values="[org.testcontainers.session-id=4c81d4efc176]"
103-
[936d82e9964e] Created container for image "redis:latest"
104-
[936d82e9964e] Starting container for image "redis:latest"...
105-
[936d82e9964e] Starting container...
106-
[936d82e9964e] Started container
107-
[936d82e9964e] Started container for image "redis:latest"
108-
[936d82e9964e] Fetching container logs...
109-
[936d82e9964e] Demuxing stream...
110-
[936d82e9964e] Demuxed stream
111-
[936d82e9964e] Fetched container logs
112-
[936d82e9964e] Waiting for container to be ready...
113-
[936d82e9964e] Waiting for host port 32775...
114-
[936d82e9964e] Waiting for internal port 6379...
115-
[936d82e9964e] 1:C 24 Mar 2025 12:10:17.419 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
116-
[936d82e9964e] 1:C 24 Mar 2025 12:10:17.419 * Redis version=7.4.2, bits=64, commit=00000000, modified=0, pid=1, just started
117-
[936d82e9964e] 1:C 24 Mar 2025 12:10:17.419 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
118-
[936d82e9964e] 1:M 24 Mar 2025 12:10:17.419 * monotonic clock: POSIX clock_gettime
119-
[936d82e9964e] 1:M 24 Mar 2025 12:10:17.419 * Running mode=standalone, port=6379.
120-
[936d82e9964e] 1:M 24 Mar 2025 12:10:17.420 * Server initialized
121-
[936d82e9964e] 1:M 24 Mar 2025 12:10:17.420 * Ready to accept connections tcp
122-
[DEBUG] [936d82e9964e] Host port 32775 ready
123-
[DEBUG] [936d82e9964e] Host port wait strategy complete
124-
[DEBUG] [936d82e9964e] Internal port 6379 ready
125-
[INFO] [936d82e9964e] Container is ready
126-
[INFO] [936d82e9964e] Stopping container...
127-
[DEBUG] [936d82e9964e] Stopping container...
128-
[936d82e9964e] 1:signal-handler (1742818217) Received SIGTERM scheduling shutdown...
129-
[DEBUG] [936d82e9964e] Stopped container
130-
[DEBUG] [936d82e9964e] Removing container...
131-
[DEBUG] [936d82e9964e] Removed container
132-
[INFO] [936d82e9964e] Stopped container
133-
```
15+
!!! note
16+
You can enable multiple loggers: `DEBUG=testcontainers,testcontainers:exec.`
13417

135-
These logs are useful for debugging when a container isn't working as expected. You can see there are logs from the Testcontainers library, as well as logs emitted from all Testcontainers-managed containers.
18+
---
19+
20+
You could for example run your tests with all Testcontainers logs enabled like this:
21+
22+
```bash
23+
DEBUG=testcontainers* npm test
24+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Resource Cleanup

docs/quickstart/usage.md

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
# Usage
22

3-
As an example, let's spin up and test a Redis container.
3+
**As an example, let's spin up and test a Redis container.**
44

5-
First, let's install the dependencies:
5+
---
6+
7+
First, install the dependencies:
68

79
```bash
10+
npm install testcontainers --save-dev
811
npm install redis
912
```
1013

11-
Using your favorite testing library, let's now create a test:
14+
---
15+
16+
Next, we'll write a test that starts a Redis container, connects to it, and performs an operation:
1217

13-
```ts
18+
```ts linenums="1" hl_lines="2 5 9-11 14 22"
1419
import { createClient, RedisClientType } from "redis";
1520
import { GenericContainer, StartedTestContainer } from "testcontainers";
1621

@@ -19,7 +24,7 @@ describe("Redis", () => {
1924
let redisClient: RedisClientType;
2025

2126
beforeAll(async () => {
22-
container = await new GenericContainer("redis")
27+
container = await new GenericContainer("redis:8")
2328
.withExposedPorts(6379)
2429
.start();
2530

@@ -44,4 +49,47 @@ describe("Redis", () => {
4449

4550
Run the test, and after a few seconds, it passes!
4651

47-
Why did it take a few seconds? Because your container runtime likely had to pull the image first. If you run the test again, it'll run faster.
52+
!!! note
53+
Why did it take a few seconds?
54+
55+
Because your container runtime first had to pull the image. If you run the test again, it'll run faster.
56+
57+
---
58+
59+
The complexity of configuring a container varies.
60+
61+
For Redis, it's pretty simple, we just expose a port. But for example, to define a `GenericContainer` for PostgreSQL, you'd need to configure multiple ports, environment variables for credentials, custom wait strategies, and more. For this reason there exists a catalogue of [pre-defined modules](https://testcontainers.com/modules/), which abstract away this complexity.
62+
63+
If a module exists for the container you want to use, it's highly recommended to use it.
64+
65+
For example, using the [Redis module](../modules/redis.md), the example above can be simplified:
66+
67+
```bash
68+
npm install @testcontainers/redis --save-dev
69+
```
70+
71+
```ts linenums="1" hl_lines="2 5 9-10"
72+
import { createClient, RedisClientType } from "redis";
73+
import { RedisContainer, StartedRedisContainer } from "@testcontainers/redis";
74+
75+
describe("Redis", () => {
76+
let container: StartedRedisContainer;
77+
let redisClient: RedisClientType;
78+
79+
beforeAll(async () => {
80+
container = await new StartedRedisContainer("redis:8").start();
81+
redisClient = createClient({ url: container.getConnectionUrl() });
82+
await redisClient.connect();
83+
});
84+
85+
afterAll(async () => {
86+
await redisClient.disconnect();
87+
await container.stop();
88+
});
89+
90+
it("works", async () => {
91+
await redisClient.set("key", "val");
92+
expect(await redisClient.get("key")).toBe("val");
93+
});
94+
});
95+
```

0 commit comments

Comments
 (0)