2323 * [ Configuring MySQL options] ( #configuring-mysql-options )
2424 * [ Setting readiness timeout] ( #setting-readiness-timeout )
2525 * [ Retrieving connection data] ( #retrieving-connection-data )
26+ * [ Environment-aware connection] ( #environment-aware-connection )
2627* [ Flyway container] ( #flyway-container )
2728 * [ Setting the database source] ( #setting-the-database-source )
2829 * [ Configuring migrations] ( #configuring-migrations )
@@ -54,6 +55,8 @@ composer require tiny-blocks/docker-container
5455Creates a container from a specified image and an optional name.
5556
5657``` php
58+ use TinyBlocks\DockerContainer\GenericDockerContainer;
59+
5760$container = GenericDockerContainer::from(image: 'php:8.5-fpm', name: 'my-container');
5861```
5962
@@ -75,6 +78,8 @@ $container->run(commands: ['ls', '-la']);
7578With commands and a wait strategy:
7679
7780``` php
81+ use TinyBlocks\DockerContainer\Waits\ContainerWaitForTime;
82+
7883$container->run(commands: ['ls', '-la'], waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5));
7984```
8085
@@ -95,6 +100,9 @@ To pull multiple images in parallel, call `pullImage()` on all containers **befo
95100them. This way the downloads happen concurrently:
96101
97102``` php
103+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
104+ use TinyBlocks\DockerContainer\FlywayDockerContainer;
105+
98106$mysql = MySQLDockerContainer::from(image: 'mysql:8.4', name: 'my-database')
99107 ->pullImage()
100108 ->withRootPassword(rootPassword: 'root');
@@ -103,11 +111,11 @@ $flyway = FlywayDockerContainer::from(image: 'flyway/flyway:12-alpine')
103111 ->pullImage()
104112 ->withMigrations(pathOnHost: '/path/to/migrations');
105113
106- // Both images are downloading in the background.
107- // MySQL pull completes here, container starts and becomes ready.
114+ # Both images are downloading in the background.
115+ # MySQL pull completes here, container starts and becomes ready.
108116$mySQLStarted = $mysql->runIfNotExists();
109117
110- // Flyway pull already finished while MySQL was starting.
118+ # Flyway pull already finished while MySQL was starting.
111119$flyway->withSource(container: $mySQLStarted, username: 'root', password: 'root')
112120 ->cleanAndMigrate();
113121```
@@ -135,8 +143,8 @@ After the container starts, both ports are available through the `Address`:
135143``` php
136144$ports = $started->getAddress()->getPorts();
137145
138- $ports->firstExposedPort(); // 80 (container-internal)
139- $ports->firstHostPort(); // 8080 (host-accessible)
146+ $ports->firstExposedPort(); # 80 (container-internal)
147+ $ports->firstHostPort(); # 8080 (host-accessible)
140148```
141149
142150### Setting volume mappings
@@ -227,6 +235,8 @@ $result->isSuccessful();
227235Pauses execution for a specified number of seconds before or after starting a container.
228236
229237``` php
238+ use TinyBlocks\DockerContainer\Waits\ContainerWaitForTime;
239+
230240$container->withWaitBeforeRun(wait: ContainerWaitForTime::forSeconds(seconds: 3));
231241```
232242
@@ -236,6 +246,11 @@ Blocks until a readiness condition is satisfied, with a configurable timeout. Th
236246depends on another being fully ready.
237247
238248``` php
249+ use TinyBlocks\DockerContainer\GenericDockerContainer;
250+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
251+ use TinyBlocks\DockerContainer\Waits\ContainerWaitForDependency;
252+ use TinyBlocks\DockerContainer\Waits\Conditions\MySQLReady;
253+
239254$mySQLStarted = MySQLDockerContainer::from(image: 'mysql:8.4')
240255 ->withRootPassword(rootPassword: 'root')
241256 ->run();
@@ -267,6 +282,8 @@ MySQL-specific configuration and automatic readiness detection.
267282| ` withGrantedHosts ` | ` $hosts ` | Sets hosts granted root privileges (default: ` ['%', '172.%'] ` ). |
268283
269284``` php
285+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
286+
270287$mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.4', name: 'my-database')
271288 ->withTimezone(timezone: 'America/Sao_Paulo')
272289 ->withUsername(user: 'app_user')
@@ -284,6 +301,8 @@ Configures how long the MySQL container waits for the database to become ready b
284301` ContainerWaitTimeout ` exception. The default timeout is 30 seconds.
285302
286303``` php
304+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
305+
287306$mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.4', name: 'my-database')
288307 ->withRootPassword(rootPassword: 'root')
289308 ->withReadinessTimeout(timeoutInSeconds: 60)
@@ -300,8 +319,8 @@ $ip = $address->getIp();
300319$hostname = $address->getHostname();
301320
302321$ports = $address->getPorts();
303- $containerPort = $ports->firstExposedPort(); // e.g. 3306 (container-internal)
304- $hostPort = $ports->firstHostPort(); // e.g. 49153 (host-accessible)
322+ $containerPort = $ports->firstExposedPort(); # e.g. 3306 (container-internal)
323+ $hostPort = $ports->firstHostPort(); # e.g. 49153 (host-accessible)
305324
306325$environmentVariables = $mySQLContainer->getEnvironmentVariables();
307326$database = $environmentVariables->getValueBy(key: 'MYSQL_DATABASE');
@@ -314,6 +333,31 @@ $jdbcUrl = $mySQLContainer->getJdbcUrl();
314333Use ` firstExposedPort() ` when connecting from another container in the same network.
315334Use ` firstHostPort() ` when connecting from the host machine (e.g., tests running outside Docker).
316335
336+ ### Environment-aware connection
337+
338+ The ` Address ` and ` Ports ` contracts provide environment-aware methods that automatically resolve the correct host and
339+ port for connecting to a container. These methods detect whether the caller is running inside Docker or on the host
340+ machine:
341+
342+ ``` php
343+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
344+
345+ $mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.4', name: 'my-database')
346+ ->withRootPassword(rootPassword: 'root')
347+ ->withDatabase(database: 'my_database')
348+ ->withPortMapping(portOnHost: 3306, portOnContainer: 3306);
349+
350+ $started = $mySQLContainer->runIfNotExists();
351+ $address = $started->getAddress();
352+
353+ $host = $address->getHostForConnection(); # hostname inside Docker, 127.0.0.1 on host
354+ $port = $address->getPorts()->getPortForConnection(); # container port inside Docker, host-mapped port on host
355+ ```
356+
357+ This is useful when the same test suite runs both locally (inside a Docker Compose stack) and in CI (on the host).
358+ Instead of manually checking the environment and switching between ` getHostname() ` /` getIp() ` or ` firstExposedPort() ` /
359+ ` firstHostPort() ` , the environment-aware methods handle it transparently.
360+
317361## Flyway container
318362
319363` FlywayDockerContainer ` provides a specialized container for running Flyway database migrations. It encapsulates
@@ -325,6 +369,8 @@ Configures the Flyway container to connect to a running MySQL container. Automat
325369target schema from ` MYSQL_DATABASE ` , and sets the history table to ` schema_history ` .
326370
327371``` php
372+ use TinyBlocks\DockerContainer\FlywayDockerContainer;
373+
328374$flywayContainer = FlywayDockerContainer::from(image: 'flyway/flyway:12-alpine')
329375 ->withNetwork(name: 'my-network')
330376 ->withMigrations(pathOnHost: '/path/to/migrations')
@@ -385,6 +431,9 @@ $flywayContainer->cleanAndMigrate();
385431Configure both containers and start image pulls in parallel before running either one:
386432
387433``` php
434+ use TinyBlocks\DockerContainer\MySQLDockerContainer;
435+ use TinyBlocks\DockerContainer\FlywayDockerContainer;
436+
388437$mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.4', name: 'test-database')
389438 ->pullImage()
390439 ->withNetwork(name: 'my-network')
0 commit comments