diego-ninja / docker
Run and manage docker containers in your php code
Fund package maintenance!
Ko Fi
paypal.me/diegorin
www.buymeacoffee.com/diegoninja
Requires
- php: ^8.2
- spatie/macroable: ^2.0
- symfony/process: ^6.0 || ^7.0
Requires (Dev)
- captainhook/captainhook: ^5.10
- captainhook/plugin-composer: ^5.3
- ergebnis/composer-normalize: ^2.30
- friendsofphp/php-cs-fixer: ^3.40
- icanhazstring/composer-unused: ^0.8.7
- maglnet/composer-require-checker: ^4.5
- pestphp/pest: ^1.22
- php-parallel-lint/php-console-highlighter: ^1.0
- php-parallel-lint/php-parallel-lint: ^1.3
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- spatie/ssh: ^1.7.0
- symfony/var-dumper: ^5.3
README
This package provides a nice way to start docker containers and execute commands on them.
$containerInstance = DockerContainer::create($imageName)->start(); $process = $containerInstance->execute('whoami'); $process->getOutput(); // returns the name of the user inside the docker container
Differences
This package is a fork of spatie/docker with some adaptations to fit my particular needs.
As major differences, this package drops php 7.x support and gives the possibility to use the library with already created containers. Also, all methods that return a Symfony process object now accept an $async flag to run the process asynchronously, using the start method instead of run method. Finally, the start method now accepts an optional callable, if present the callable will be called continuously as the container runs, this callable will take the Symfony Process object as its only parameter.
$containerInstance = DockerContainerInstance::fromExisting("test-runner"); // uses a running container $spinner = new Spinner("Running unit tests...") // starts a console spinner $process = $containerInstance->execute('php vendor/bin/phpunit', true); // starts process asynchronous while($process->isRunning()) { $spinner->advance(); // updates spinner usleep(2000); } $process->isSuccessful() ? $spinner->success() : $spinner->error(); // finishes spinner based on result
Installation
You can install the package via composer:
composer require diego-ninja/docker
Usage
You can get an instance of a docker container using
$containerInstance = DockerContainer::create($imageName)->start();
By default, the container will be daemonized, and it will be cleaned up after it exists.
Customizing the docker container
Prevent daemonization
If you don't want your docker being daemonized, call doNotDaemonize
.
$containerInstance = DockerContainer::create($imageName) ->doNotDaemonize() ->start();
Prevent automatic clean up
If you don't want your docker being cleaned up after it exists, call doNotCleanUpAfterExit
.
$containerInstance = DockerContainer::create($imageName) ->doNotCleanUpAfterExit() ->start();
Privileged
If you want your docker being privileged, call privileged
.
$containerInstance = DockerContainer::create($imageName) ->privileged() ->start();
Custom shell
If the bash
shell is not available in your docker image, you can specify an alternative shell.
$containerInstance = DockerContainer::create($imageName) ->shell('sh') ->start();
Naming the container
You can name the container by passing the name as the second argument to the constructor.
new DockerContainer($imageName, $nameOfContainer);
Alternatively, use the name
method.
$containerInstance = DockerContainer::create($imageName) ->name($yourName) ->start();
Mapping ports
You can map ports between the host machine and the docker container using the mapPort
method. To map multiple ports, just call mapPort
multiple times.
$containerInstance = DockerContainer::create($imageName) ->mapPort($portOnHost, $portOnContainer) ->mapPort($anotherPortOnHost, $anotherPortOnContainer) ->start();
Environment variables
You can set environment variables using the setEnvironmentVariable
method. To add multiple arguments, just call setEnvironmentVariable
multiple times.
$containerInstance = DockerContainer::create($imageName) ->setEnvironmentVariable($variableKey, $variableValue) ->setEnvironmentVariable($anotherVariableKey, $anotherVariableValue) ->start();
Setting Volumes
You can set volumes using the setVolume
method. To add multiple arguments, just call setVolume
multiple times.
$containerInstance = DockerContainer::create($imageName) ->setVolume($pathOnHost, $pathOnDocker) ->setVolume($anotherPathOnHost, $anotherPathOnDocker) ->start();
Setting Labels
You can set labels using the setLabel
method. To add multiple arguments, just call setLabel
multiple times.
$containerInstance = DockerContainer::create($imageName) ->setLabel($labelName, $labelValue) ->setLabel($anotherLabelName, $anotherLabelValue) ->start();
Adding Commands
You can add commands using the setCommands
method.
$containerInstance = DockerContainer::create($imageName) ->setCommands('--api.insecure=true', '--providers.docker=true') ->start();
These commands will be placed at the end of to the docker run
command.
Add optional arguments
If you want to add optional arguments to the docker run
command, use setOptionalArgs
method:
$containerInstance = DockerContainer::create($imageName) ->setOptionalArgs('-it', '-a') ->start();
These arguments will be placed after docker run
immediately.
Automatically stopping the container after PHP exists
When using this package in a testing environment, it can be handy that the docker container is stopped after __destruct
is called on it (mostly this will happen when the PHP script ends). You can enable this behaviour with the stopOnDestruct
method.
$containerInstance = DockerContainer::create($imageName) ->stopOnDestruct() ->start();
Attaching a network to the container
If you want to attach the container to a docker network, use network
method:
$containerInstance = DockerContainer::create($imageName) ->network('my-network') ->start();
Specify a remote docker host for execution
You can set the host used for executing the container. The docker
command line accepts a daemon socket string. To connect to a remote docker host via ssh, use the syntax ssh://username@hostname
. Note that the proper SSH keys will already need to be configured for this work.
$containerInstance = DockerContainer::create($imageName) ->remoteHost('ssh://username@hostname') ->start();
Specify an alternative command to execute
Upon startup of a container, docker will execute the command defined within the container. The command
method gives the ability to override to default command to run within the container.
$containerInstance = DockerContainer::create($imageName) ->command('ls -l /etc') ->start();
Getting the start command string
You can get the string that will be executed when a container is started with the getStartCommand
function
// returns "docker run -d --rm spatie/docker" DockerContainer::create($imageName)->getStartCommand();
Changing the start command timeout
You can change the timeout for the start command with the setStartCommandTimeout
function (the default is 60s).
$containerInstance = DockerContainer::create($imageName) ->setStartCommandTimeout(120) ->start();
Available methods on the docker container instance
Executing a command
To execute a command on the container, use the execute
method.
$process = $instance->execute($command);
You can execute multiple command in one go by passing an array.
$process = $instance->execute([$command, $anotherCommand]); $asyncProcess = $instance->execute([$command, $anotherCommand], true);
To change the process timeout you can pass a third parameter to the execute
method (the default is 60s).
$process = $instance->execute([$command, $anotherCommand], false, 3600);
The execute method returns an instance of Symfony/Process
.
You can check if your command ran successfully using the isSuccessful
$method
$process->isSuccessful(); // returns a boolean
You can get to the output using getOutput()
. If the command did not run successfully, you can use getErrorOutput()
. For more information on how to work with a Process
head over to the Symfony docs.
Installing a public key
If you cant to connect to your container instance via SSH, you probably want to add a public key to it.
This can be done using the addPublicKey
method.
$instance->addPublicKey($pathToPublicKey);
It is assumed that the authorized_keys
file is located in at /root/.ssh/authorized_keys
. If this is not the case, you can specify the path of that file as a second parameter.
$instance->addPublicKey($pathToPublicKey, $pathToAuthorizedKeys);
Note that in order to be able to connect via SSH, you should set up a SSH server in your dockerfile
. Take a look at the dockerfile
in the tests of this package for an example.
Adding files to your instance
Files can be added to an instance with addFiles
.
$instance->addFiles($fileOrDirectoryOnHost, $pathInContainer);
Get the docker inspect information
The json decoded array from the docker inspect command can be retrieved with inspect
.
$inspectArray = $instance->inspect(); $inspectArray[0]['State']['Status']; // Running, Starting etc. $inspectArray[0]['RestartCount']; // Integer $inspectArray[0]['NetworkSettings']['IPAddress']; // 172.17.0.2
Adding other functions on the docker instance
The Ninja\Docker\ContainerInstance
class is macroable. This means you can add extra functions to it.
Ninja\Docker\DockerContainerInstance::macro('whoAmI', function () { $process = $containerInstance->run('whoami'); return $process->getOutput(); }); $containerInstance = DockerContainer::create($imageName)->start(); $containerInstance->whoAmI(); // returns of name of user in the docker container
Testing
Before running the tests for the first time, you must build the spatie/docker
container with:
composer build-docker
Next, you can run the tests with:
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you've found a bug regarding security please mail security@spatie.be instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.