clue / docker-react
基于 ReactPHP 的异步、事件驱动的 Docker Engine API 访问。
Requires
- php: >=5.3
- clue/json-stream: ^0.1
- react/event-loop: ^1.2
- react/http: ^1.8
- react/promise: ^3.1 || ^2.11 || ^1.3
- react/promise-stream: ^1.6
- react/socket: ^1.12
- react/stream: ^1.2
- rize/uri-template: ^0.3
Requires (Dev)
- clue/caret-notation: ^0.2
- clue/tar-react: ^0.2
- phpunit/phpunit: ^9.6 || ^5.7 || ^4.8.36
- react/async: ^4 || ^3 || ^2
README
基于 ReactPHP 的异步、事件驱动的 Docker Engine API 访问。
Docker 是一个流行的开源平台,可以在隔离、轻量级容器中运行和共享应用程序。Docker Engine API 允许您控制和监控您的容器和镜像。例如,它可以用来列出现有的镜像、下载新的镜像、在隔离的容器中执行任意命令、停止正在运行的容器等。这个轻量级库提供了从 PHP 中高效工作与 Docker Engine API 的方法。它使您能够处理其镜像和容器,或使用其事件驱动模型来响应发生的更改和事件。
- 异步执行动作 - 并行向您的 Docker 守护进程发送任意数量的动作(命令),并在结果到来时立即处理它们的响应。基于 Promise 的设计提供了一个 合理的 接口来处理无序的响应。
- 轻量级、SOLID 设计 - 提供了一个足够薄的抽象,不会阻碍您。这个库只是围绕 Docker Engine API 的一个非常薄的包装。
- 良好的测试覆盖率 - 随附自动测试套件,并在实际环境中定期测试。
目录
支持我们
我们在开发、维护和更新我们出色的开源项目上投入了大量时间。您可以通过 成为 GitHub 的赞助商 来帮助我们维持我们工作的这种高质量。赞助商将获得许多回报,请参阅我们的 赞助页面 以获取详细信息。
让我们共同将这些项目提升到新的水平!🚀
快速入门示例
安装后,您可以使用以下代码访问本地 docker 守护进程的 Docker API
<?php require __DIR__ . '/vendor/autoload.php'; $client = new Clue\React\Docker\Client(); $client->imageSearch('clue')->then(function (array $images) { var_dump($images); }, function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; });
另请参阅 示例。
用法
客户端
Client
负责组装并发送 HTTP 请求到 Docker Engine API。
$client = new Clue\React\Docker\Client();
这个类接受一个可选的 LoopInterface|null $loop
参数,可以用来传递用于此对象的事件循环实例。您可以使用 null
值来使用默认循环。除非您确信要显式使用给定的事件循环实例,否则不应提供此值。
如果您的Docker Engine API无法通过默认的Unix域套接字路径unix:///var/run/docker.sock
访问,您可以选择性地传递一个明确的URL,例如这样
// explicitly use given UNIX socket path $client = new Clue\React\Docker\Client(null, 'unix:///var/run/docker.sock'); // or connect via TCP/IP to a remote Docker Engine API $client = new Clue\React\Docker\Client(null, 'http://10.0.0.2:8000/');
命令
Client
上的所有公共方法都类似于Docker Engine API文档中描述的API,如下所示
$client->containerList($all, $size); $client->containerCreate($config, $name); $client->containerStart($name); $client->containerKill($name, $signal); $client->containerRemove($name, $v, $force); $client->imageList($all); $client->imageSearch($term); $client->imageCreate($fromImage, $fromSrc, $repo, $tag, $registry, $registryAuth); $client->info(); $client->version(); // many, many more…
在这里列出所有可用的命令超出了范围,请参阅Docker Engine API文档或类概要。
这些命令都支持异步操作,要么通过其结果进行解析,要么通过一个Exception
进行拒绝。请参阅以下关于承诺的部分以获取更多详细信息。
Promises
发送请求是异步的(非阻塞的),因此您可以实际上并行发送多个请求。Docker将使用响应消息响应每个请求,顺序没有保证。发送请求使用基于Promise的接口,这使得在命令完成时(即成功完成或因错误而拒绝)做出反应变得简单。
$client->version()->then( function ($result) { var_dump('Result received', $result); }, function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; } });
如果您觉得这很奇怪,您还可以使用更传统的阻塞API。
阻塞
如上所述,这个库默认提供了一个强大、异步的API。
您也可以通过使用reactphp/async将其集成到您的传统、阻塞环境中。这允许您像这样简单地等待客户端上的命令
use function React\Async\await; $client = new Clue\React\Docker\Client(); $promise = $client->imageInspect('busybox'); try { $results = await($promise); // results successfully received } catch (Exception $e) { // an error occurred while performing the request }
类似地,您还可以并发处理多个命令并等待一个结果数组
use function React\Async\await; use function React\Promise\all; $promises = array( $client->imageInspect('busybox'), $client->imageInspect('ubuntu'), ); $inspections = await(all($promises));
这是由于PHP 8.1+中可用的纤维以及我们兼容的API(该API也适用于所有支持的PHP版本)而成为可能的。请参阅reactphp/async以获取更多详细信息。
命令流
以下API端点通过命令输出的缓冲字符串(STDOUT和/或STDERR)进行解析
$client->containerAttach($container); $client->containerLogs($container); $client->execStart($exec);
请注意,这意味着整个字符串必须保留在内存中。如果您想按发生时的顺序访问单个输出块或对于更大的命令输出,通常使用流式传输方法会更好。
这对于(任意数量的)任意大小的命令都适用。以下API端点补充了默认的Promise-based API,并返回一个Stream
实例
$stream = $client->containerAttachStream($container); $stream = $client->containerLogsStream($container); $stream = $client->execStartStream($exec);
结果流是一个表现良好的可读流,将发出正常的流事件
$stream = $client->execStartStream($exec, $tty); $stream->on('data', function ($data) { // data will be emitted in multiple chunk echo $data; }); $stream->on('error', function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; }); $stream->on('close', function () { // the stream just ended, this could(?) be a good thing echo 'Ended' . PHP_EOL; });
请注意,默认情况下,STDOUT和STDERR的输出将作为正常的data
事件发出。您可以可选地传递一个自定义事件名称,该名称将用于发出STDERR数据,以便可以单独处理。请注意,正常的流原语可能不了解此事件,因此可能需要特别注意。另外,请注意,如果您以TTY执行,此选项没有效果。
$stream = $client->execStartStream($exec, $tty, 'stderr'); $stream->on('data', function ($data) { echo 'STDOUT data: ' . $data; }); $stream->on('stderr', function ($data) { echo 'STDERR data: ' . $data; });
TTY模式应根据您的命令是否需要TTY来设置。请注意,切换TTY模式会影响您如何/是否可以访问STDERR流,并且对大流(对于数百兆字节及以上的流)的性能有重大影响。有关execStart*()
调用中的TTY模式,请参阅相关说明。
在多种系统上运行提供的基准测试示例表明,该库可以每秒处理数GB数据,实际上可能优于Docker客户端,并且似乎仅受Docker Engine实现的限制。与其在这里发布更多细节,不如鼓励您自己重新运行基准测试,亲自验证。关键结论是:PHP可能比您想象的要快。
TAR 流
以下API端点返回的是TAR文件格式的字符串
$client->containerExport($container); $client->containerArchive($container, $path);
请注意,这意味着整个字符串必须保存在内存中。对于较小的文件/容器,这很容易启动并且表现良好。
对于较大的容器,通常使用流式方法会更好,其中只需要保持内存中的小块数据。这适用于任意大小的文件。以下API端点补充了默认的基于Promise的API,并返回一个Stream
实例
$stream = $client->containerExportStream($image); $stream = $client->containerArchiveStream($container, $path);
访问TAR文件格式字符串或流中的单个文件超出了本库的功能范围。有几个库可用,其中一个已知可以正常工作的是clue/reactphp-tar。
JSON 流
以下API端点利用了JSON流
$client->imageCreate(); $client->imagePush(); $client->events();
这意味着这些端点实际上会发出任意数量的进度事件(单个JSON对象)。在HTTP级别,一个常见的响应消息可能如下所示
HTTP/1.1 200 OK
Content-Type: application/json
{"status":"loading","current":1,"total":10}
{"status":"loading","current":2,"total":10}
…
{"status":"loading","current":10,"total":10}
{"status":"done","total":10}
用户API通过在流结束时解析所有单个进度事件来隐藏这个事实
$client->imageCreate('clue/streamripper')->then( function (array $data) { // $data is an array of *all* elements in the JSON stream var_dump($data); }, function (Exception $e) { // an error occurred (possibly after receiving *some* elements) echo 'Error: ' . $e->getMessage() . PHP_EOL; } );
请注意,由于解析所有进度事件的数组,此API必须将所有事件对象保留在内存中,直到Promise解析。对于上述API端点,这很容易启动并且通常表现良好。
如果您正在处理大量的并发请求(100+)或者想要在事件发生时访问单个进度事件,您应考虑使用流式方法,其中只需要保持内存中的单个进度事件对象。以下API端点补充了默认的基于Promise的API,并返回一个Stream
实例
$stream = $client->imageCreateStream(); $stream = $client->imagePushStream(); $stream = $client->eventsStream(); $stream = $client->containerStatsStream($container);
生成的流将发出以下事件
data
:对于更新流中的每个元素error
:一旦发生错误,就会关闭流- 如果单个进度消息包含错误消息或任何其他
Exception
(例如传输错误,如无效请求等),将发出RuntimeException
- 如果单个进度消息包含错误消息或任何其他
close
:一旦流结束(无论是完成还是“错误”)
$stream = $client->imageCreateStream('clue/redis-benchmark'); $stream->on('data', function (array $data) { // data will be emitted for *each* complete element in the JSON stream echo $data['status'] . PHP_EOL; }); $stream->on('error', function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; }); $stream->on('close', function () { // the JSON stream just ended, this could(?) be a good thing echo 'Ended' . PHP_EOL; });
安装
安装此库的推荐方法是通过Composer。 Composer新手?
本项目遵循SemVer。这将安装最新支持的版本
composer require clue/docker-react:^1.5
请参阅CHANGELOG以获取有关版本升级的详细信息。
本项目旨在在任何平台上运行,因此不需要任何PHP扩展,并支持在旧版PHP 5.3至当前PHP 8+上运行。对于本项目,强烈建议使用最新支持的PHP版本。
测试
要运行测试套件,首先需要克隆此仓库,然后通过Composer安装所有依赖项(Composer)
composer install
要运行测试套件,请转到项目根目录并运行
vendor/bin/phpunit
许可
本项目遵循宽松的MIT许可协议。
你知道吗?我提供定制开发服务,并为发布赞助和贡献开具发票。如需详细了解,请联系我(@clue)。