The DockerContainer library provides an interface and implementations to manage Docker containers programmatically.
It simplifies the creation, execution, and interaction with containers, such as adding network configurations, mapping
ports, setting environment variables, and executing commands inside containers.
Designed specifically to support unit tests and integration tests, the library enables developers to simulate
and manage containerized environments with minimal effort, ensuring a seamless testing workflow.
composer require tiny-blocks/docker-containerCreates a container from a specified image and optionally a name.
The from method initializes a new container instance with an image and an optional name for identification.
$container = GenericDockerContainer::from(image: 'php:8.3-fpm', name: 'my-container');The run method starts a container.
Optionally, it allows you to execute commands within the container after it has started and define a condition to wait
for using a ContainerWaitAfterStarted instance.
Example with no commands or conditions:
$container->run();Example with commands only:
$container->run(commands: ['ls', '-la']);Example with commands and a wait condition:
$container->run(commands: ['ls', '-la'], waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5));The runIfNotExists method starts a container only if it doesn't already exist.
$container->runIfNotExists();Example with commands and a wait condition:
$container->runIfNotExists(commands: ['ls', '-la'], waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5));The withNetwork method connects the container to a specified Docker network by name.
$container->withNetwork(name: 'my-network');Maps ports between the host and the container. Multiple port mappings are supported.
$container->withPortMapping(portOnHost: 9000, portOnContainer: 9000);
$container->withPortMapping(portOnHost: 8080, portOnContainer: 80);Maps a volume from the host to the container.
$container->withVolumeMapping(pathOnHost: '/path/on/host', pathOnContainer: '/path/in/container');Sets environment variables inside the container.
$container->withEnvironmentVariable(key: 'XPTO', value: '123');Prevents the container from being automatically removed when stopped.
$container->withoutAutoRemove();Copies files or directories from the host machine to the container.
$container->copyToContainer(pathOnHost: '/path/to/files', pathOnContainer: '/path/in/container');The withWaitBeforeRun method allows the container to pause its execution until a specified condition is met before
starting. A timeout prevents the wait from blocking indefinitely.
$container->withWaitBeforeRun(
wait: ContainerWaitForDependency::untilReady(
condition: MySQLReady::from(container: $container),
timeoutInSeconds: 30
)
);The withReadinessTimeout method configures how long the MySQL container will wait for the database to become ready
before throwing a ContainerWaitTimeout exception. The default timeout is 30 seconds.
$container = MySQLDockerContainer::from(image: 'mysql:8.1', name: 'my-database')
->withReadinessTimeout(timeoutInSeconds: 60)
->run();-
When running the containers from the library on a host (your local machine), you need to map the volume
/var/run/docker.sock:/var/run/docker.sock. This ensures that the container has access to the Docker daemon on the host machine, allowing Docker commands to be executed within the container. -
In some cases, it may be necessary to add the
docker-clidependency to your PHP image. This enables the container to interact with Docker from within the container environment.
Before configuring and starting the MySQL container, a PHP container is set up to execute the tests and manage the integration process.
This container runs within a Docker network and uses a volume for the database migrations. The following commands are used to prepare the environment:
-
Create the Docker network:
docker network create tiny-blocks
-
Create the volume for migrations:
docker volume create test-adm-migrations
-
Run the PHP container:
docker run -u root --rm -it --network=tiny-blocks --name test-lib \ -v ${PWD}:/app \ -v ${PWD}/tests/Integration/Database/Migrations:/test-adm-migrations \ -v /var/run/docker.sock:/var/run/docker.sock \ -w /app gustavofreze/php:8.5-alpine bash -c "composer tests"
The MySQL container is configured and started:
$mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.1', name: 'test-database')
->withNetwork(name: 'tiny-blocks')
->withTimezone(timezone: 'America/Sao_Paulo')
->withUsername(user: 'xpto')
->withPassword(password: '123')
->withDatabase(database: 'test_adm')
->withPortMapping(portOnHost: 3306, portOnContainer: 3306)
->withRootPassword(rootPassword: 'root')
->withGrantedHosts()
->withReadinessTimeout(timeoutInSeconds: 60)
->withoutAutoRemove()
->runIfNotExists();With the MySQL container started, it is possible to retrieve data, such as the address and JDBC connection URL:
$environmentVariables = $mySQLContainer->getEnvironmentVariables();
$jdbcUrl = $mySQLContainer->getJdbcUrl();
$database = $environmentVariables->getValueBy(key: 'MYSQL_DATABASE');
$username = $environmentVariables->getValueBy(key: 'MYSQL_USER');
$password = $environmentVariables->getValueBy(key: 'MYSQL_PASSWORD');The Flyway container is configured and only starts and executes migrations after the MySQL container is ready:
$flywayContainer = GenericDockerContainer::from(image: 'flyway/flyway:11.0.0')
->withNetwork(name: 'tiny-blocks')
->copyToContainer(pathOnHost: '/test-adm-migrations', pathOnContainer: '/flyway/sql')
->withVolumeMapping(pathOnHost: '/test-adm-migrations', pathOnContainer: '/flyway/sql')
->withWaitBeforeRun(
wait: ContainerWaitForDependency::untilReady(
condition: MySQLReady::from(
container: $mySQLContainer
),
timeoutInSeconds: 30
)
)
->withEnvironmentVariable(key: 'FLYWAY_URL', value: $jdbcUrl)
->withEnvironmentVariable(key: 'FLYWAY_USER', value: $username)
->withEnvironmentVariable(key: 'FLYWAY_TABLE', value: 'schema_history')
->withEnvironmentVariable(key: 'FLYWAY_SCHEMAS', value: $database)
->withEnvironmentVariable(key: 'FLYWAY_EDITION', value: 'community')
->withEnvironmentVariable(key: 'FLYWAY_PASSWORD', value: $password)
->withEnvironmentVariable(key: 'FLYWAY_LOCATIONS', value: 'filesystem:/flyway/sql')
->withEnvironmentVariable(key: 'FLYWAY_CLEAN_DISABLED', value: 'false')
->withEnvironmentVariable(key: 'FLYWAY_VALIDATE_MIGRATION_NAMING', value: 'true')
->run(
commands: ['-connectRetries=15', 'clean', 'migrate'],
waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5)
);Docker container is licensed under MIT.
Please follow the contributing guidelines to contribute to the project.