spatie/docker
Start and manage Docker containers from PHP. Create and run containers, execute commands inside them, and capture output. Customize behavior like daemonization, auto-cleanup on exit, and privileged mode for more control.
Installation:
composer require spatie/docker
Requires Docker to be installed and running on your system.
First Use Case: Start a container and execute a command:
use Spatie\Docker\DockerContainer;
$container = DockerContainer::create('alpine:latest')
->start();
$output = $container->execute('echo "Hello Docker!"')->getOutput();
echo $output; // "Hello Docker!"
Where to Look First:
start(), stop(), execute(), and getOutput().Spin up disposable containers for PHPUnit tests (e.g., databases, services):
use Spatie\Docker\DockerContainer;
beforeEach(function () {
$this->container = DockerContainer::create('mysql:8.0')
->withPorts(['3306:3306'])
->withEnvironment(['MYSQL_ROOT_PASSWORD' => 'secret'])
->start();
});
afterEach(function () {
$this->container->stop();
});
Run commands inside containers (e.g., migrations, CLI tools):
$container = DockerContainer::create('composer:latest')->start();
$output = $container->execute('composer install')->getOutput();
Reuse containers across tests or scripts:
$container = DockerContainer::create('redis:alpine')
->start()
->stop(); // Stop when done
Use in Artisan commands or service providers:
use Spatie\Docker\DockerContainer;
class DeployCommand extends Command
{
protected $signature = 'deploy:docker';
public function handle()
{
$container = DockerContainer::create('your-app-image')->start();
$container->execute('php artisan migrate');
}
}
Build containers with custom options:
$container = DockerContainer::create('node:18')
->withWorkingDirectory('/app')
->withMountedDirectory('/local/path', '/container/path')
->start();
Error Handling:
Wrap container operations in try-catch blocks to handle DockerException:
try {
$container->start();
} catch (DockerException $e) {
Log::error('Docker failed: ' . $e->getMessage());
}
Environment Variables:
Pass secrets or configs via withEnvironment():
->withEnvironment([
'DB_HOST' => 'localhost',
'APP_KEY' => env('APP_KEY'),
])
Port Mapping: Expose ports for local development or testing:
->withPorts(['8000:80'])
Logging: Stream container logs in real-time:
$container->start();
$container->logs(function ($output) {
echo $output;
});
Docker Daemon Access:
docker group on Linux).docker:dind (Docker-in-Docker) if Docker isn’t pre-installed.Resource Limits:
stop() or remove() after use:
$container->stop()->remove();
Image Availability:
if (!$container->imageExists()) {
$container->pull();
}
Command Timeouts:
withTimeout():
->execute('long-running-command', 300) // 5-minute timeout
Port Conflicts:
->withPorts(['0:80']) // Random host port
Inspect Container:
Use getInspection() to debug container state:
$inspection = $container->getInspection();
dd($inspection['State']); // Check 'Running', 'ExitCode', etc.
Logs: Capture logs for troubleshooting:
$logs = $container->getLogs();
Process Output: Check raw output (stdout/stderr) separately:
$process = $container->execute('ls /nonexistent');
$process->getOutput(); // stdout
$process->getErrorOutput(); // stderr
Reuse Containers: Cache container instances for repeated use (e.g., in tests):
static $redisContainer;
if (!$redisContainer) {
$redisContainer = DockerContainer::create('redis:alpine')->start();
}
Custom Entrypoints: Override container entrypoints:
->withEntrypoint(['/custom-script.sh'])
Volume Mounts: Persist data between container runs:
->withMountedDirectory('/host/path', '/container/path')
Health Checks: Verify container readiness before use:
$container->start();
if (!$container->isRunning()) {
throw new RuntimeException('Container failed to start');
}
Cleanup:
Automate cleanup in afterEach() (tests) or finally blocks:
try {
$container->start();
// ... use container ...
} finally {
$container->stop()->remove();
}
Networking: Connect containers to custom networks:
->withNetwork('your-network-name')
Platform-Specific Quirks:
npipe for Docker Desktop interactions.DOCKER_HOST is set if using remote Docker daemons.Performance: Reuse images to avoid repeated pulls:
$container->pullIfNotExists();
How can I help you explore Laravel packages today?