clue/docker-react

基于 ReactPHP 的异步、事件驱动的 Docker Engine API 访问。

v1.5.0 2024-05-03 10:28 UTC

This package is auto-updated.

Last update: 2024-09-03 11:16:52 UTC


README

CI status installs on Packagist

基于 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;
});

请参阅拉取示例推送示例

安装

安装此库的推荐方法是通过ComposerComposer新手?

本项目遵循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)。