Skip to content

Commit 20d8f8c

Browse files
committed
More docs and modules
1 parent 677eaea commit 20d8f8c

11 files changed

Lines changed: 545 additions & 0 deletions

File tree

docs/configuration.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Configuration
2+
3+
## Container runtime access
4+
5+
Testcontainers for PHP uses Docker APIs under the hood, so your test process must be able to reach a Docker-compatible daemon.
6+
7+
- Local socket: `unix:///var/run/docker.sock`
8+
- Remote daemon: configure `DOCKER_HOST`
9+
10+
## Environment variables
11+
12+
### `DOCKER_HOST`
13+
14+
Defines where the Docker API is available.
15+
Examples:
16+
17+
```bash
18+
export DOCKER_HOST=tcp://127.0.0.1:2375
19+
export DOCKER_HOST=unix:///var/run/docker.sock
20+
```
21+
22+
### `TESTCONTAINERS_HOST_OVERRIDE`
23+
24+
Overrides the host address returned by Testcontainers when your tests need a custom endpoint:
25+
26+
```bash
27+
export TESTCONTAINERS_HOST_OVERRIDE=127.0.0.1
28+
```
29+
30+
## Running inside containers
31+
32+
If your tests run inside another container:
33+
34+
- Mount the Docker socket.
35+
- Ensure network routing from test container to started containers is valid.
36+
- Set host overrides when needed for your CI/network topology.
37+
38+
For startup and connectivity failures, see [troubleshooting](troubleshooting.md).

docs/features/containers.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Containers
2+
3+
## Starting a container
4+
5+
Start any image with `GenericContainer`:
6+
7+
```php
8+
<?php
9+
10+
use Testcontainers\Container\GenericContainer;
11+
12+
$container = (new GenericContainer('alpine:3.20'))
13+
->withCommand(['sleep', 'infinity'])
14+
->start();
15+
```
16+
17+
## Common container options
18+
19+
### Environment variables
20+
21+
```php
22+
$container = (new GenericContainer('alpine:3.20'))
23+
->withEnvironment([
24+
'APP_ENV' => 'test',
25+
'FEATURE_X' => 'enabled',
26+
])
27+
->start();
28+
```
29+
30+
### Exposed ports
31+
32+
```php
33+
$container = (new GenericContainer('nginx:alpine'))
34+
->withExposedPorts(80)
35+
->start();
36+
37+
$host = $container->getHost();
38+
$port = $container->getMappedPort(80);
39+
```
40+
41+
### Files and directories
42+
43+
```php
44+
$container = (new GenericContainer('alpine:3.20'))
45+
->withCommand(['sleep', 'infinity'])
46+
->withCopyFilesToContainer([
47+
['source' => __DIR__ . '/app.conf', 'target' => '/etc/app.conf'],
48+
])
49+
->withCopyContentToContainer([
50+
['content' => 'hello from php', 'target' => '/tmp/message.txt'],
51+
])
52+
->start();
53+
```
54+
55+
### Networking
56+
57+
`withNetwork()` connects the container to an existing Docker network. Create the network before starting the container, for example with `docker network create my-test-network`.
58+
59+
```php
60+
$container = (new GenericContainer('alpine:3.20'))
61+
->withNetwork('my-test-network')
62+
->withAliases(['service-a'])
63+
->start();
64+
```
65+
66+
### User, working directory, labels, and mounts
67+
68+
```php
69+
$container = (new GenericContainer('alpine:3.20'))
70+
->withUser('1000:1000')
71+
->withWorkingDir('/app')
72+
->withLabels(['suite' => 'integration'])
73+
->withMount(__DIR__, '/workspace')
74+
->start();
75+
```
76+
77+
## Stopping and restarting
78+
79+
```php
80+
$container->restart();
81+
$container->stop();
82+
```
83+
84+
`stop()` stops and removes the container.
85+
86+
Related docs: [wait strategies](wait-strategies.md), [networking](networking.md).

docs/features/networking.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Networking
2+
3+
Testcontainers for PHP maps container ports to random host ports by default.
4+
5+
## Access a service from your test process
6+
7+
Use `getHost()` and `getMappedPort()`:
8+
9+
```php
10+
<?php
11+
12+
declare(strict_types=1);
13+
14+
use Testcontainers\Container\GenericContainer;
15+
use Testcontainers\Wait\WaitForHttp;
16+
17+
$container = (new GenericContainer('nginx:alpine'))
18+
->withExposedPorts(80)
19+
->withWait((new WaitForHttp(80))->withPath('/'))
20+
->start();
21+
22+
$url = sprintf('http://%s:%d', $container->getHost(), $container->getMappedPort(80));
23+
echo $url . PHP_EOL;
24+
25+
$container->stop();
26+
```
27+
28+
## Use the first mapped port
29+
30+
If a container exposes only one port, use `getFirstMappedPort()`:
31+
32+
```php
33+
$port = $container->getFirstMappedPort();
34+
```
35+
36+
## Join a Docker network
37+
38+
Connect multiple containers to the same existing Docker network and use aliases. Testcontainers for PHP does not create Docker networks, so create the network before starting containers:
39+
40+
```bash
41+
docker network create my-test-network
42+
```
43+
44+
```php
45+
<?php
46+
47+
declare(strict_types=1);
48+
49+
use Testcontainers\Container\GenericContainer;
50+
51+
$container = (new GenericContainer('alpine'))
52+
->withCommand(['tail', '-f', '/dev/null'])
53+
->withNetwork('my-test-network')
54+
->withAliases(['service-a'])
55+
->start();
56+
57+
$container->stop();
58+
```
59+
60+
## Notes
61+
62+
- Do not hardcode localhost ports in tests.
63+
- Always resolve endpoints from `getHost()` and mapped ports.
64+
- Named networks and aliases are useful for container-to-container communication.
65+
66+
Related docs: [containers](containers.md), [configuration](../configuration.md), [troubleshooting](../troubleshooting.md).

docs/features/wait-strategies.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Wait strategies
2+
3+
Wait strategies define when a container is ready to use.
4+
5+
`GenericContainer` defaults to a running-state check (`WaitForContainer`).
6+
For application readiness, prefer explicit strategies described below.
7+
8+
## Host port (default-friendly)
9+
10+
```php
11+
<?php
12+
13+
use Testcontainers\Container\GenericContainer;
14+
use Testcontainers\Wait\WaitForHostPort;
15+
16+
$container = (new GenericContainer('redis:7'))
17+
->withExposedPorts(6379)
18+
->withWait(new WaitForHostPort())
19+
->start();
20+
```
21+
22+
## Log output
23+
24+
```php
25+
use Testcontainers\Wait\WaitForLog;
26+
27+
$container = (new GenericContainer('redis:7'))
28+
->withExposedPorts(6379)
29+
->withWait(new WaitForLog('Ready to accept connections'))
30+
->start();
31+
```
32+
33+
With regular expression matching:
34+
35+
```php
36+
$container = (new GenericContainer('opensearchproject/opensearch:latest'))
37+
->withExposedPorts(9200)
38+
->withWait(new WaitForLog('/\]\s+started\?\[/', true, 30_000))
39+
->start();
40+
```
41+
42+
## HTTP checks
43+
44+
```php
45+
use Testcontainers\Wait\WaitForHttp;
46+
47+
$container = (new GenericContainer('nginx:alpine'))
48+
->withExposedPorts(80)
49+
->withWait(
50+
(new WaitForHttp(80))
51+
->withPath('/')
52+
->withExpectedStatusCode(200)
53+
)
54+
->start();
55+
```
56+
57+
## Exec command
58+
59+
```php
60+
use Testcontainers\Wait\WaitForExec;
61+
62+
$container = (new GenericContainer('mysql:8.0'))
63+
->withExposedPorts(3306)
64+
->withEnvironment(['MYSQL_ROOT_PASSWORD' => 'root'])
65+
->withWait(new WaitForExec(['mysqladmin', 'ping', '-h', '127.0.0.1']))
66+
->start();
67+
```
68+
69+
With custom validation:
70+
71+
```php
72+
$container = (new GenericContainer('mysql:8.0'))
73+
->withExposedPorts(3306)
74+
->withEnvironment(['MYSQL_ROOT_PASSWORD' => 'root'])
75+
->withWait(
76+
new WaitForExec(
77+
['mysqladmin', 'ping', '-h', '127.0.0.1'],
78+
static function ($exitCode, $output): bool {
79+
return $exitCode === 0 && str_contains($output, 'mysqld is alive');
80+
}
81+
)
82+
)
83+
->start();
84+
```
85+
86+
## Docker health check
87+
88+
```php
89+
use Testcontainers\Wait\WaitForHealthCheck;
90+
91+
$container = (new GenericContainer('alpine'))
92+
->withCommand(['tail', '-f', '/dev/null'])
93+
->withHealthCheckCommand('echo "healthy" || exit 1')
94+
->withWait(new WaitForHealthCheck())
95+
->start();
96+
```
97+
98+
!!! tip
99+
You can tune timeout and polling intervals in wait strategy constructors.
100+
101+
Related docs: [containers](containers.md), [networking](networking.md), [troubleshooting](../troubleshooting.md).

docs/modules/mariadb.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# MariaDB
2+
3+
`MariaDBContainer` configures MariaDB and waits for `mariadb-admin ping`.
4+
5+
## Requirements
6+
7+
- PHP extension: `ext-pdo_mysql`
8+
9+
```php
10+
<?php
11+
12+
declare(strict_types=1);
13+
14+
use Testcontainers\Modules\MariaDBContainer;
15+
16+
$container = (new MariaDBContainer())
17+
->withMariaDBDatabase('foo')
18+
->withMariaDBUser('bar', 'baz')
19+
->start();
20+
21+
try {
22+
$pdo = new PDO(
23+
sprintf('mysql:host=%s;port=%d', $container->getHost(), $container->getFirstMappedPort()),
24+
'bar',
25+
'baz',
26+
);
27+
28+
$query = $pdo->query('SHOW databases');
29+
$databases = $query->fetchAll(PDO::FETCH_COLUMN);
30+
} finally {
31+
$container->stop();
32+
}
33+
```

docs/modules/mongodb.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# MongoDB
2+
3+
`MongoDBContainer` configures credentials and waits until `mongosh` can execute a command.
4+
5+
## Requirements
6+
7+
- PHP extension: `ext-mongodb`
8+
9+
```php
10+
<?php
11+
12+
declare(strict_types=1);
13+
14+
use Testcontainers\Modules\MongoDBContainer;
15+
16+
$container = (new MongoDBContainer())->start();
17+
18+
try {
19+
$pingResult = $container->exec([
20+
'mongosh',
21+
'admin',
22+
'-u',
23+
'test',
24+
'-p',
25+
'test',
26+
'--eval',
27+
'\'db.runCommand("ping").ok\'',
28+
]);
29+
30+
echo $pingResult;
31+
} finally {
32+
$container->stop();
33+
}
34+
```

docs/modules/mysql.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# MySQL
2+
3+
`MySQLContainer` configures MySQL and waits for `mysqladmin ping`.
4+
5+
## Requirements
6+
7+
- PHP extension: `ext-pdo_mysql`
8+
9+
```php
10+
<?php
11+
12+
declare(strict_types=1);
13+
14+
use Testcontainers\Modules\MySQLContainer;
15+
16+
$container = (new MySQLContainer())
17+
->withMySQLDatabase('foo')
18+
->withMySQLUser('bar', 'baz')
19+
->start();
20+
21+
try {
22+
$pdo = new PDO(
23+
sprintf('mysql:host=%s;port=%d', $container->getHost(), $container->getFirstMappedPort()),
24+
'bar',
25+
'baz',
26+
);
27+
28+
$query = $pdo->query('SHOW databases');
29+
$databases = $query->fetchAll(PDO::FETCH_COLUMN);
30+
} finally {
31+
$container->stop();
32+
}
33+
```

0 commit comments

Comments
 (0)