diego-ninja / docker
Run and manage docker containers in your php code
Fund package maintenance!
Ko Fi
paypal.me/diegorin
www.buymeacoffee.com/diegoninja
Installs: 2 165
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 56
pkg:composer/diego-ninja/docker
Requires
- php: ^8.4
- spatie/macroable: ^2.0
- symfony/process: ^7.0
Requires (Dev)
- captainhook/captainhook: ^5.10
- captainhook/plugin-composer: ^5.3
- ergebnis/composer-normalize: ^2.30
- friendsofphp/php-cs-fixer: ^v3
- icanhazstring/composer-unused: ^0.9.5
- maglnet/composer-require-checker: ^4.11
- pestphp/pest: ^4.0
- php-parallel-lint/php-console-highlighter: ^1.0
- php-parallel-lint/php-parallel-lint: ^1.4
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- spatie/ssh: ^1.7.0
- symfony/polyfill-iconv: ^1.33
- symfony/var-dumper: ^7.0
README
This package provides a fluent, modern API to start and manage Docker containers directly from your PHP code. It is a fork of spatie/docker with significant improvements in ergonomics, security, and functionality.
Key Features
- ✅ Ergonomic Facade API: A static
Dockerfacade that simplifies container creation (Docker::nginx()->start()). - ✅ Type-Safe: Thanks to PHP 8.4 and the intensive use of immutable Value Objects (
ImageName,ContainerPath,Port) to validate all inputs. - ✅ Secure: Prevents command injection by validating all parameters through Value Objects.
- ✅ SSH Agent Forwarding: Securely allows containers to access the host's SSH keys.
- ✅ Extensible: Register your own custom services on the
Facadeto reuse configurations. - ✅ Well-Tested: Over 95% test coverage.
Installation
You can install the package via Composer. It requires PHP 8.4 or higher.
composer require diego-ninja/docker
Quick Start
The easiest way to use the package is through the Docker facade.
use Ninja\Docker\Docker; // Start a Nginx container on port 8080 $container = Docker::image('nginx:latest') ->port(8080, 80) ->name('my-nginx') ->start(); echo "Container started. IP: " . $container->getIp() . "\n"; // Execute a command inside the container $output = $container->execute('ls -la /usr/share/nginx/html'); echo $output; // Stop and remove the container $container->stop();
Key Differences with spatie/docker
This package is a fork of spatie/docker, but it introduces significant improvements:
- Facade for a Simplified API: The
Dockerfacade provides a static, expressive, and easy-to-remember API, ideal for frameworks like Laravel or for quick usage.// Before (and still works) (new DockerContainer('nginx:latest'))->port(8080, 80)->start(); // Now (recommended) Docker::image('nginx:latest')->port(8080, 80)->start();
- Type Safety with Value Objects: Instead of using raw strings and numbers, the library uses Value Objects to validate every parameter, preventing common errors and attacks.
// Encourages using Value Objects for clarity and safety use Ninja\Docker\ValueObjects\HostPath; use Ninja\Docker\ValueObjects\ContainerPath; Docker::image('...')->volume( HostPath::from(__DIR__ . '/content'), ContainerPath::from('/usr/share/nginx/html') );
- Specific Exceptions: More descriptive exceptions, like
CouldNotStartDockerContainer, have been added to make debugging easier.
Detailed Usage
1. Using the Facade (Recommended)
The Docker facade offers three ways to create containers:
a) Shortcuts for Common Services
It includes shortcuts for the most popular services with pre-defined configurations.
// Nginx on port 80 Docker::nginx()->start(); // MySQL 8 with a root password Docker::mysql(['password' => 'secret'])->start(); // PostgreSQL 16 with a password Docker::postgres(['password' => 'secret', 'database' => 'my_app'])->start(); // Redis Docker::redis()->start();
You can pass a configuration array to customize the service:
// MySQL with a database, user, and persistent data directory Docker::mysql([ 'password' => 'root_secret', 'database' => 'my_app', 'user' => 'app_user', 'user_password' => 'user_pass', 'data_dir' => '/path/on/host/for/data', // Volume mount for persistence 'port' => 3307, // Custom host port ])->start();
b) Generic container() Builder
For any image that doesn't have a shortcut, use the container() method.
Docker::container('alpine:latest') ->command('sleep', '300') // Keeps the container running ->start();
c) Registering Custom Services
You can register your own shortcuts, for example, in your application's bootstrap file.
// Register a service once Docker::register('mailhog', [ 'image' => 'mailhog/mailhog', 'ports' => [1025 => 1025, 8025 => 8025], 'name_prefix' => 'mailhog', ]); // Use it anywhere in your code Docker::mailhog()->start();
2. Fluent API
All facade methods return a DockerContainer instance, so you can continue to use the fluent API to override or add configurations.
Docker::mysql(['password' => 'secret']) ->port(3307, 3306) // Override the default port ->namedVolume('mysql-data', '/var/lib/mysql') // Use a named volume ->network('backend') // Add to a network ->start();
3. Configuration Examples
Port Mapping
Use port(hostPort, containerPort).
->port(8080, 80)
Volume Mapping
- Bind Mount: Mounts a host path into the container.
use Ninja\Docker\ValueObjects\HostPath; use Ninja\Docker\ValueObjects\ContainerPath; ->volume(HostPath::from('/path/on/host'), ContainerPath::from('/path/in/container'))
- Named Volume: Uses a Docker-managed volume.
use Ninja\Docker\ValueObjects\VolumeName; use Ninja\Docker\ValueObjects\ContainerPath; ->namedVolume(VolumeName::from('my-volume'), ContainerPath::from('/path/in/container'))
Environment Variables
->environment('MY_VAR', 'its_value') ->environment('ANOTHER_VAR', 'another_value')
4. Interacting with Running Containers
The start() method returns a DockerContainerInstance.
$container = Docker::nginx()->start(); // Get the container's IP address $ip = $container->getIp(); // Execute a command $output = $container->execute('whoami'); // returns "root" // Get the container ID $id = $container->getContainerId(); // Check if it's running if ($container->isRunning()) { // ... } // Stop the container $container->stop();
You can also connect to an already running container.
$container = DockerContainerInstance::fromExisting('my-nginx'); $container->execute('echo "Hello from an existing container"');
Testing
Before running the tests for the first time, you need to build the Docker image for testing:
composer build-docker
Then, you can run the full test suite with Pest:
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING.md for details. Contributions are welcome.
Security
If you've found a security vulnerability, please email yosoy@diego.ninja instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see the License File for more information.