feat(serve): Docker Engine API daemon foundation (mocker serve)#45
Merged
Conversation
…eadlock runCLI read stdout/stderr inside terminationHandler, which only fires after the process exits. When output exceeds the ~64KB pipe buffer the child blocks on write before it can exit, so the handler never fires and the call hangs forever (surfaced by the API server issuing large `container ls`/`inspect`). Drain both pipes on detached tasks while the process runs; readDataToEndOfFile returns at EOF when the process exits and closes the pipe.
Add `mocker serve`, a Docker Engine API server on a Unix socket so DOCKER_HOST tooling can talk to mocker. Phase 1 read-only foundation: GET/HEAD /_ping and GET /version with correct version negotiation (advertise API 1.47, MinAPIVersion 1.24, lenient /vX.YY path stripping — never enforce min/max). SwiftNIO over a unix domain socket at $HOME/.docker/run/docker.sock, owner-only (0600) with a safe lstat preflight that refuses to clobber a non-socket. JSON emitted with unescaped slashes for Docker parity. Verified: real `docker version` negotiates (1.54 -> 1.47) and connects. See .context/docker-api-plan.md for the full phased plan (plan-loop reviewed).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
mocker serve— a Docker Engine API server on a Unix socket so the wholeDOCKER_HOSTecosystem (thedockerCLI, testcontainers, IDE plugins, CI, language SDKs) can talk to mocker. This is Phase 1 (read-only foundation) of a phased plan; it proves the approach end-to-end.Why
mocker is Docker-CLI-compatible but had no socket/API. Tools that talk to the daemon socket (not the CLI) couldn't use it. Socket compatibility is the feature that makes a "real Docker alternative" (it's OrbStack's actual moat).
Changes
fix(engine):runCLIdrained stdout/stderr insideterminationHandler, which deadlocks when output exceeds the ~64KB pipe buffer (the child blocks on write before it can exit). Now drains both pipes concurrently. Prerequisite for the API server issuing largecontainer ls/inspect.feat(serve):DockerAPIServer(SwiftNIO over a unix socket) + theservecommand.GET/HEAD /_ping,GET /versionwith correct version negotiation (advertise API1.47,MinAPIVersion 1.24, lenient/vX.YYpath stripping — never enforce min/max, since testcontainers pins low versions into the path).$HOME/.docker/run/docker.sock, owner-only0600, safelstatpreflight that refuses to clobber a non-socket / symlink.Api-Versionheader on every response.Verification (tested from all angles)
swift test: 239/239 (7 new). Includes a test proving the drain fix reads 1.3 MB without deadlocking (the exact scenario the old code hung on), path-leniency (/v1.32/,/v9.99/,/volumesedge case), and socket-safety (refuses a non-socket file).dockerCLI:docker versionnegotiates1.54 -> 1.47and connects (Server: mocker / OS/Arch: linux/arm64).404 {"message":...}, 10 concurrent requests, keep-alive,docker info/psfail cleanly (no hang), socket-safety.Scope / next
Read-only only. Engine-backed endpoints (
/info,/containers/json,/images/json,/containers/{id}/json) come next (they add the NIO↔actor bridge).docker run+ testcontainers are Phase 2/3. Full phased plan (plan-loop reviewed, 2 iterations):.context/docker-api-plan.md.