diego-ninja/docker

Run and manage docker containers in your php code

Installs: 2 165

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 56

pkg:composer/diego-ninja/docker

v2.1.0 2025-11-22 21:16 UTC

This package is auto-updated.

Last update: 2025-11-24 00:17:56 UTC


README

Latest Version on Packagist Total Downloads PHP Version License: MIT GitHub last commit wakatime

Tests Static Analysis Code Style Coveralls

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 Docker facade 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 Facade to 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:

  1. Facade for a Simplified API: The Docker facade 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();
  2. 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')
    );
  3. 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.