sharryy/docker-sandbox
Composer 安装命令:
composer require sharryy/docker-sandbox
包简介
A simple, secure and fluent PHP API for running untrusted code in isolated Docker containers.
README 文档
README
A simple, secure and fluent PHP API for running untrusted code in isolated
Docker containers. It talks directly to the Docker Engine API over a unix
socket or TCP/TLS — no shelling out to the docker CLI — and makes the
easiest way to run code also the most locked-down one.
Installation
composer require sharryy/docker-sandbox
Requires PHP 8.3+, the cURL extension, and access to a Docker daemon (Docker Desktop, Colima, Lima, or a remote daemon over TCP/TLS).
Note: The package is developed and tested on Linux and macOS. Windows is not supported or tested — the test suite requires a Linux Docker daemon.
Quick start
use Sharryy\Docker\Sandbox; $sandbox = new Sandbox(); $result = $sandbox->php('<?php echo 2 + 2;'); $result->output(); // "4" $result->exitCode(); // 0 $result->successful(); // true $result->duration(); // seconds
python and node presets ship out of the box:
$sandbox->python('print(6 * 7)')->output(); // "42" $sandbox->node('console.log(6 * 7)')->output(); // "42"
Register your own preset
use Sharryy\Docker\{Sandbox, Preset}; // Preset(image, filename, interpreter) Sandbox::register('ruby', new Preset('ruby:3.3-slim', 'main.rb', 'ruby')); $sandbox->run('ruby', 'puts "hello"')->output(); // "hello"
A custom preset with the same name overrides a built-in one.
Secure by default
Every Sandbox/run() execution is locked down. The container has no
network, runs as a non-root user, on a read-only root filesystem
with only a small writable /tmp tmpfs, with all Linux capabilities
dropped, no-new-privileges, no swap, and a process limit (so a
fork bomb can't take down the host). Missing images are pulled automatically,
and a timeout kills runaway code:
use Sharryy\Docker\Exceptions\ProcessTimeoutException; try { $sandbox->php('<?php while (true) {}', timeout: 5); } catch (ProcessTimeoutException $e) { // the container was killed and removed }
ExecutionResult exposes output(), errorOutput(), exitCode(),
successful(), failed(), timedOut(), oomKilled() and duration().
Connecting to a daemon
use Sharryy\Docker\{Docker, ConnectionOptions}; // Auto-discovers the socket (DOCKER_HOST, default, Colima, Docker Desktop) $docker = new Docker(); // Or be explicit: $docker = new Docker(ConnectionOptions::fromSocket('/var/run/docker.sock')); $docker = new Docker(ConnectionOptions::fromTcp('127.0.0.1', 2375)); $docker = new Docker(ConnectionOptions::fromTls('docker.example.com', 2376, caCert: '/certs/ca.pem', clientCert: '/certs/cert.pem', clientKey: '/certs/key.pem'));
The API version is negotiated with the daemon automatically.
Building containers
For long-lived or custom containers, use the fluent builder:
$container = $docker->containers() ->from('redis:alpine') ->withName('cache') ->withCommand(['redis-server']) ->withPort(6379, 6379) ->withMemoryLimit('256m') ->withCpuLimit(0.5) // security hardening (all opt-in here) ->withUser('1000:1000') ->asReadOnly() ->withTmpfs('/tmp') ->withPidsLimit(128) ->dropCapabilities() ->withoutNewPrivileges() ->withoutSwap() ->withUlimit('nofile', 1024) ->create(); $container->start();
Interacting with a container
$container->status(); // 'created' | 'running' | 'exited' | 'paused' | ... $container->isRunning(); $container->logs(); // combined stdout + stderr $container->inspect(); // full inspect payload $container->stats(); // one-shot CPU/memory/network snapshot $container->pause(); $container->unpause(); $container->restart(); $container->rename('new-name'); $container->stop()->remove(); // Run a command and read its result $result = $container->exec(['redis-cli', 'ping']); $result->output(); // "PONG" $result->exitCode(); // 0 // Follow output in real time $container->streamLogs(function (string $text, string $stream) { // $stream is "stdout" or "stderr" echo $text; });
Moving files in and out
use Sharryy\Docker\Support\Tar; $container->putFiles([ 'app/main.php' => '<?php echo "hi";', 'app/lib.php' => '<?php /* ... */', ]); $tar = $container->getArchive('/app'); // raw tar of the directory
Images
$images = $docker->images(); $images->exists('php:8.2-cli'); $images->pull('php:8.2-cli'); // optional registry auth arg $images->list(); // repo tags $images->remove('php:8.2-cli', force: true); $images->prune(); // remove dangling images
Finding & listing containers
$container = $docker->containers()->find('cache'); // by id or name, or null $all = $docker->containers()->list(all: true); // array of Container objects
Testing
The test suite runs against a real Docker daemon:
composer test
Network-heavy tests (pulling images in run(), and the python/node presets)
are skipped unless DOCKER_PULL_TESTS=1 is set.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover a security vulnerability, please review our security policy for how to report it responsibly.
Credits
License
The MIT License (MIT). Please see License File for more information.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-22