|
1 | | -# docker-container |
2 | | -Manage Docker containers programmatically, simplifying the creation, running, and interaction with containers. |
| 1 | +# Docker container |
| 2 | + |
| 3 | +[](LICENSE) |
| 4 | + |
| 5 | +* [Overview](#overview) |
| 6 | +* [Installation](#installation) |
| 7 | +* [How to use](#how-to-use) |
| 8 | + * [Creating a container](#creating-a-container) |
| 9 | + * [Running a container](#running-a-container) |
| 10 | + * [Running a container if it doesn't exist](#running-a-container-if-it-doesnt-exist) |
| 11 | + * [Setting network](#setting-network) |
| 12 | + * [Setting port mappings](#setting-port-mappings) |
| 13 | + * [Setting volumes mappings](#setting-volumes-mappings) |
| 14 | + * [Setting environment variables](#setting-environment-variables) |
| 15 | + * [Disabling auto-remove](#disabling-auto-remove) |
| 16 | + * [Copying files to a container](#copying-files-to-a-container) |
| 17 | + * [Waiting for a condition](#waiting-for-a-condition) |
| 18 | +* [Usage examples](#usage-examples) |
| 19 | +* [License](#license) |
| 20 | +* [Contributing](#contributing) |
| 21 | + |
| 22 | +<div id='overview'></div> |
| 23 | + |
| 24 | +## Overview |
| 25 | + |
| 26 | +The `DockerContainer` library provides an interface and implementations to manage Docker containers programmatically. |
| 27 | +It simplifies the creation, execution, and interaction with containers, such as adding network configurations, mapping |
| 28 | +ports, setting environment variables, and executing commands inside containers. |
| 29 | +Designed specifically to support **unit tests** and **integration tests**, the library enables developers to simulate |
| 30 | +and manage containerized environments with minimal effort, ensuring a seamless testing workflow. |
| 31 | + |
| 32 | +<div id='installation'></div> |
| 33 | + |
| 34 | +## Installation |
| 35 | + |
| 36 | +```bash |
| 37 | +composer require tiny-blocks/docker-container |
| 38 | +``` |
| 39 | + |
| 40 | +<div id='how-to-use'></div> |
| 41 | + |
| 42 | +## How to use |
| 43 | + |
| 44 | +### Creating a container |
| 45 | + |
| 46 | +Creates a container from a specified image and optionally a name. |
| 47 | +The `from` method can be used to initialize a new container instance with an image and an optional name for |
| 48 | +identification. |
| 49 | + |
| 50 | +```php |
| 51 | +$container = GenericDockerContainer::from(image: 'php:8.3-fpm', name: 'my-container'); |
| 52 | +``` |
| 53 | + |
| 54 | +### Running a container |
| 55 | + |
| 56 | +The `run` method starts a container. |
| 57 | +Optionally, it allows you to execute commands within the container after it has started and define a condition to wait |
| 58 | +for using a `ContainerWaitAfterStarted` instance. |
| 59 | + |
| 60 | +**Example with no commands or conditions:** |
| 61 | + |
| 62 | +```php |
| 63 | +$container->run(); |
| 64 | +``` |
| 65 | + |
| 66 | +**Example with commands only:** |
| 67 | + |
| 68 | +```php |
| 69 | +$container->run(commands: ['ls', '-la']); |
| 70 | +``` |
| 71 | + |
| 72 | +**Example with commands and a wait condition:** |
| 73 | + |
| 74 | +```php |
| 75 | +$container->run(commands: ['ls', '-la'], waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5)); |
| 76 | +``` |
| 77 | + |
| 78 | +### Running a container if it doesn't exist |
| 79 | + |
| 80 | +The `runIfNotExists` method starts a container only if it doesn't already exist. |
| 81 | +Optionally, it allows you to execute commands within the container after it has started and define a condition to wait |
| 82 | +for using a `ContainerWaitAfterStarted` instance. |
| 83 | + |
| 84 | +```php |
| 85 | +$container->runIfNotExists(); |
| 86 | +``` |
| 87 | + |
| 88 | +**Example with commands only:** |
| 89 | + |
| 90 | +```php |
| 91 | +$container->runIfNotExists(commands: ['ls', '-la']); |
| 92 | +``` |
| 93 | + |
| 94 | +**Example with commands and a wait condition:** |
| 95 | + |
| 96 | +```php |
| 97 | +$container->runIfNotExists(commands: ['ls', '-la'], waitAfterStarted: ContainerWaitForTime::forSeconds(seconds: 5)); |
| 98 | +``` |
| 99 | + |
| 100 | +### Setting network |
| 101 | + |
| 102 | +The `withNetwork` method connects the container to a specified Docker network by name, allowing you to define the |
| 103 | +network configuration the container will use. |
| 104 | + |
| 105 | +```php |
| 106 | +$container->withNetwork(name: 'my-network'); |
| 107 | +``` |
| 108 | + |
| 109 | +### Setting port mappings |
| 110 | + |
| 111 | +Maps ports between the host and the container. |
| 112 | +The `withPortMapping` method maps a port from the host to a port inside the container. |
| 113 | + |
| 114 | +```php |
| 115 | +$container->withPortMapping(portOnHost: 9000, portOnContainer: 9000); |
| 116 | +``` |
| 117 | + |
| 118 | +### Setting volumes mappings |
| 119 | + |
| 120 | +Maps a volume from the host to the container. |
| 121 | +The `withVolumeMapping` method allows you to link a directory from the host to the container. |
| 122 | + |
| 123 | +```php |
| 124 | +$container->withVolumeMapping(pathOnHost: '/path/on/host', pathOnContainer: '/path/in/container'); |
| 125 | +``` |
| 126 | + |
| 127 | +### Setting environment variables |
| 128 | + |
| 129 | +Sets environment variables inside the container. |
| 130 | +The `withEnvironmentVariable` method allows you to configure environment variables within the container. |
| 131 | + |
| 132 | +```php |
| 133 | +$container->withEnvironmentVariable(key: 'XPTO', value: '123'); |
| 134 | +``` |
| 135 | + |
| 136 | +### Disabling auto-remove |
| 137 | + |
| 138 | +Prevents the container from being automatically removed when stopped. |
| 139 | +By default, Docker removes containers after they stop. |
| 140 | +The `withoutAutoRemove` method disables this feature, keeping the container around even after it finishes its |
| 141 | +execution. |
| 142 | + |
| 143 | +```php |
| 144 | +$container->withoutAutoRemove(); |
| 145 | +``` |
| 146 | + |
| 147 | +### Copying files to a container |
| 148 | + |
| 149 | +Copies files or directories from the host machine to the container. |
| 150 | +The `copyToContainer` method allows you to transfer files from the host system into the container’s file system. |
| 151 | + |
| 152 | +```php |
| 153 | +$container->copyToContainer(pathOnHost: '/path/to/files', pathOnContainer: '/path/in/container'); |
| 154 | +``` |
| 155 | + |
| 156 | +### Waiting for a condition |
| 157 | + |
| 158 | +The `withWaitBeforeRun` method allows the container to pause its execution until a specified condition is met before |
| 159 | +starting. |
| 160 | + |
| 161 | +```php |
| 162 | +$container->withWaitBeforeRun(wait: ContainerWaitForDependency::untilReady(condition: MySQLReady::from(container: $container))); |
| 163 | +``` |
| 164 | + |
| 165 | +<div id='usage-examples'></div> |
| 166 | + |
| 167 | +## Usage examples |
| 168 | + |
| 169 | +### MySQL and Generic Containers |
| 170 | + |
| 171 | +The MySQL container is configured and started: |
| 172 | + |
| 173 | +```php |
| 174 | +$mySQLContainer = MySQLDockerContainer::from(image: 'mysql:8.1', name: 'test-database') |
| 175 | + ->withNetwork(name: 'tiny-blocks') |
| 176 | + ->withTimezone(timezone: 'America/Sao_Paulo') |
| 177 | + ->withUsername(user: 'xpto') |
| 178 | + ->withPassword(password: '123') |
| 179 | + ->withDatabase(database: 'test_adm') |
| 180 | + ->withPortMapping(portOnHost: 3306, portOnContainer: 3306) |
| 181 | + ->withRootPassword(rootPassword: 'root') |
| 182 | + ->withVolumeMapping(pathOnHost: '/var/lib/mysql', pathOnContainer: '/var/lib/mysql') |
| 183 | + ->withoutAutoRemove() |
| 184 | + ->runIfNotExists(); |
| 185 | +``` |
| 186 | + |
| 187 | +With the MySQL container started, it is possible to retrieve data, such as the address and JDBC connection URL: |
| 188 | + |
| 189 | +```php |
| 190 | +$jdbcUrl = $mySQLContainer->getJdbcUrl(options: 'useUnicode=yes&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false'); |
| 191 | +$database = $environmentVariables->getValueBy(key: 'MYSQL_DATABASE'); |
| 192 | +$username = $environmentVariables->getValueBy(key: 'MYSQL_USER'); |
| 193 | +$password = $environmentVariables->getValueBy(key: 'MYSQL_PASSWORD'); |
| 194 | +``` |
| 195 | + |
| 196 | +The Flyway container is configured and only starts and executes migrations after the MySQL container is **ready**: |
| 197 | + |
| 198 | +```php |
| 199 | +$flywayContainer = GenericDockerContainer::from(image: 'flyway/flyway:11.0.0') |
| 200 | + ->withNetwork(name: 'tiny-blocks') |
| 201 | + ->copyToContainer(pathOnHost: '/migrations', pathOnContainer: '/flyway/sql') |
| 202 | + ->withVolumeMapping(pathOnHost: '/migrations', pathOnContainer: '/flyway/sql') |
| 203 | + ->withWaitBeforeRun( |
| 204 | + wait: ContainerWaitForDependency::untilReady( |
| 205 | + condition: MySQLReady::from( |
| 206 | + container: $mySQLContainer |
| 207 | + ) |
| 208 | + ) |
| 209 | + ) |
| 210 | + ->withEnvironmentVariable(key: 'FLYWAY_URL', value: $jdbcUrl) |
| 211 | + ->withEnvironmentVariable(key: 'FLYWAY_USER', value: $username) |
| 212 | + ->withEnvironmentVariable(key: 'FLYWAY_TABLE', value: 'schema_history') |
| 213 | + ->withEnvironmentVariable(key: 'FLYWAY_SCHEMAS', value: $database) |
| 214 | + ->withEnvironmentVariable(key: 'FLYWAY_EDITION', value: 'community') |
| 215 | + ->withEnvironmentVariable(key: 'FLYWAY_PASSWORD', value: $password) |
| 216 | + ->withEnvironmentVariable(key: 'FLYWAY_LOCATIONS', value: 'filesystem:/flyway/sql') |
| 217 | + ->withEnvironmentVariable(key: 'FLYWAY_CLEAN_DISABLED', value: 'false') |
| 218 | + ->withEnvironmentVariable(key: 'FLYWAY_VALIDATE_MIGRATION_NAMING', value: 'true') |
| 219 | + ->run(commands: ['-connectRetries=15', 'clean', 'migrate']); |
| 220 | +``` |
| 221 | + |
| 222 | +<div id='license'></div> |
| 223 | + |
| 224 | +## License |
| 225 | + |
| 226 | +Docker container is licensed under [MIT](LICENSE). |
| 227 | + |
| 228 | +<div id='contributing'></div> |
| 229 | + |
| 230 | +## Contributing |
| 231 | + |
| 232 | +Please follow the [contributing guidelines](https://github.com/tiny-blocks/tiny-blocks/blob/main/CONTRIBUTING.md) to |
| 233 | +contribute to the project. |
0 commit comments