beluga-php/docker-php
A PHP client for the Docker Engine API, offering a clean object-oriented way to manage containers, images, networks, and volumes programmatically. Ideal for building Docker-powered tooling, deployment scripts, and infrastructure workflows in PHP.
Architecture fit. This is a low-level infrastructure SDK, not an application-domain library. It speaks the Docker Engine API over a Unix socket (/var/run/docker.sock), TCP (tcp://host:2375), or TLS — it does not provide Laravel integration of any kind (no service provider, facade, config publishing, or queue/event hooks). Architecturally it belongs at the edge of the platform, in the provisioning/orchestration tier: ephemeral preview environments, sandboxed user-code execution, integration-test harnesses, build pipelines, or internal developer tooling. It should not sit in a user-facing request path for a conventional Laravel CRUD application. Treat it as a transport-layer dependency behind your own interface, never as a directly-called package in controllers or jobs.
Integration feasibility. Feasible but entirely hand-rolled. Realistic effort is 3–5 engineer-days for a hardened wrapper (config, DI binding, error mapping, retry/timeouts, stream handling) plus test infrastructure, assuming the package's transport behaves. The dependency surface is the primary friction: it will pull a specific Guzzle major version and a PHP version floor, both of which must reconcile with the host Laravel app's lockfile. Because the package is archived, there is no Laravel-aware documentation, no published container bindings, and no upgrade guide — every integration decision is yours to make and defend.
Technical risk. High, concentrated in four areas:
logs --follow, attach, events, build — require genuine streaming/chunked-response handling. If the client buffers entire responses into memory, log tailing and image builds will blow PHP memory limits under realistic payload sizes.Key questions for the package owner / spike.
Stack fit. Framework-agnostic and therefore stack-neutral: it will run under Laravel 10/11/12 on PHP 8.x provided the Guzzle constraint resolves. The correct integration shape is an internal adapter, not direct consumption:
ContainerRuntime contract in our own namespace (create, start, stop, exec, streamLogs, remove).beluga-php/docker-php, bound as a singleton via a service provider.config/docker.php — socket path, host/TLS, API version, default timeouts, label namespace for resource ownership.App\Support\Docker or a private Composer VCS package) on day one. Given archival status, this is not optional; it converts an unmaintained dependency into code we own and can patch. The MIT license permits this.Migration path. Nothing to migrate from if we are greenfield here — the risk is adopting prematurely. Sequence:
Compatibility. Gate on: PHP version floor vs. our supported matrix; Guzzle major version vs. laravel/framework's HTTP client; Docker Engine API version vs. the daemons on our hosts (which we may not control — managed Kubernetes nodes, for example, often expose an older embedded daemon or none at all); and host OS (Unix socket works on Linux/macOS, not on Windows without named-pipe support). If our runtime is Kubernetes, note that this package addresses Docker, not the Kubernetes API — its relevance drops sharply.
Sequencing note. Do not adopt in the same release as any other infrastructure change. The abstraction layer must land and be exercised by tests before real daemon calls appear in any workflow, so that removing the package later is a one-file change.
Maintenance. Effectively total ownership. There is no upstream to file issues against, no CVE response, and no release train. Budget a standing maintenance line: quarterly review of Docker Engine API deprecations against our pinned client, plus ad-hoc patches when a daemon upgrade breaks a call. With 47 stars, the bus factor is approximately one, and that one has stopped. The fork-with-internal-namespace decision exists specifically to make this cost bounded rather than open-ended.
Support. No vendor, no SLA, no community of scale. Internal runbook required: how to diagnose a failed container create, where daemon logs live, how to identify and reap containers created by our label namespace. On-call engineers will be debugging Docker daemon semantics, not PHP semantics — plan for that in escalation paths.
Scaling. The Docker daemon is the bottleneck and a shared single point of contention; a PHP client cannot fix that. Concrete constraints:
logs --follow calls can starve the queue.Failure modes to design for.
| Failure | Symptom | Mitigation |
|---|---|---|
| Daemon unreachable / socket permissions | Connection refused, opaque exceptions | Health check; explicit config validation at boot |
| API version mismatch after daemon upgrade | 400 "client version too new/old" | Negotiation, or pin and test on upgrade |
| Blocking stream never terminates | Worker pool exhaustion | Hard timeouts, --since/--tail bounded reads |
| Image pull timeout / registry auth | Jobs hang or fail mid-provision | Pull timeout, retry with backoff, pre-pulled base images |
| Container leak on partial failure | Disk exhaustion, port conflicts | Try/finally removal; label-based reconciler |
| TLS certificate expiry | Sudden total failure | Cert expiry alerting |
| Unmapped daemon error (409/500) | Silent success or generic 500 | Typed exception mapping in the adapter |
Ramp-up. The API surface is small and learnable in a day for an engineer who already understands Docker. The real ramp-up cost is organizational: teams must internalize that container lifecycle is stateful, async, and failure-prone in ways normal Laravel work is not — partial provisioning, retries that must be idempotent, and resource cleanup. Expect two to three weeks before an engineer is productive and confident here, plus a written runbook. Do not expect this to be a "composer require and go" dependency; it is infrastructure code that happens to be written in PHP.
Overall recommendation. The abstraction-first, fork-and-vendor approach makes this acceptable for bounded internal tooling, but the archived status disqualifies it from any customer-facing or security-sensitive path. Treat the 9.29 score as unvalidated metadata given the archival flag and 47-star community, and require the spike in step 1 to pass before committing further.
How can I help you explore Laravel packages today?