定制 sharryy/docker-sandbox 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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

Latest Version on Packagist Tests Total Downloads

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

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-22