microsoft / microsoft/vscode-documentdb

Consider a direct Engine API ping for Docker readiness (nice to have)

Open
#839 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement P3
Dominant language
TypeScript
Stars
31
Forks
22
Avg merge
2d 20h
Merged PRs (30d)
21

Description

Context

Local Quick Start gained a proper Docker readiness pipeline in the work tracked by docs/ai-and-plans/local-quickstart/docker-readiness-implementation-plan.md.

Important background for anyone reading this later: everything Docker related in this extension goes through @microsoft/vscode-container-client (^0.5.4), which is not an Engine API SDK. It builds docker CLI argument arrays and hands them to a runner that spawns the process (spawnStreamAsync in @microsoft/vscode-processutils, which is child_process.spawn plus tree-kill on cancellation). For example client.info({}) produces docker info --format {{json .}}. We never hand write docker argv, and we never spawn the docker binary ourselves.

Readiness today, in src/services/localQuickStart/DockerReadinessService.ts and src/services/localQuickStart/dockerProbes.ts:

  1. docker -v and docker info --format {{json .}} run concurrently under one shared deadline.
  2. docker context ls --format {{json .}} runs only in the failure branch, to resolve the active endpoint.
  3. A direct endpoint reachability probe uses fs.access and net.connect against the resolved unix socket or named pipe, which yields locale independent EACCES, ENOENT, and ECONNREFUSED.

The gap

net.connect proves that something is listening on the endpoint. It does not prove that a healthy Docker daemon is answering. The two differ in real situations:

  • Docker Desktop mid start: the socket exists and accepts connections before the engine is ready.
  • A stale socket file held open by a leftover process or a proxy.
  • A DOCKER_HOST pointed at a TCP port that some other service occupies.

Today those land in the unknown or indeterminate bucket, or they get classified from docker info stderr text, which is the least stable evidence source we have.

Proposal

After the endpoint has been resolved (which we already do, and which is what keeps us consistent with the CLI's own configuration resolution), optionally issue one Engine API request against that same endpoint:

GET /_ping  ->  200, body "OK", plus API-Version and Docker-Experimental response headers

Node's built in http module supports this with no new dependency:

http.request({ socketPath: '/var/run/docker.sock', path: '/_ping', method: 'GET' });

On Windows the same call works against \\.\pipe\docker_engine. Roughly twenty lines, plus a timeout and an abort signal wired to the existing readiness deadline.

Why this is nice to have and not required

  • We deliberately keep the CLI as the single Docker access path. The CLI is not just a transport, it is the resolver for DOCKER_HOST, DOCKER_CONTEXT, currentContext in ~/.docker/config.json, TLS material, and ssh:// endpoints. A second, independently configured path risks readiness and provisioning talking to different daemons, which is a harder failure to diagnose than the ones we set out to fix.
  • The proposal above avoids that risk only because it reuses the endpoint the CLI told us about. That constraint is the entire point and must not be dropped if this is picked up.
  • Current classification already covers the common failures well. This closes a narrow gap.

Non goals

  • Replacing the CLI with dockerode or a hand rolled Engine API client. This was evaluated and rejected: such a client does not resolve Docker contexts, TLS material, or ssh:// endpoints, and registry credential helpers on pull would still require spawning docker-credential-* helper processes and implementing their stdio protocol.
  • Using the ping for anything other than diagnosis. No pull, run, or inspect over the API.

Acceptance criteria if picked up

  • The ping runs only against an endpoint already resolved by the documented precedence (DOCKER_HOST, then DOCKER_CONTEXT, then current context, then platform default).
  • The ping is bounded by the shared readiness deadline and is cancellable.
  • A ping result may only move an indeterminate verdict toward daemonUnavailable or daemonStarting. It must never turn an uncertain result into a confidently wrong stated cause.
  • Both the unix socket and the Windows named pipe paths are covered by tests.
  • No new runtime dependency.

References

  • Plan: docs/ai-and-plans/local-quickstart/docker-readiness-implementation-plan.md
  • src/services/localQuickStart/DockerReadinessService.ts
  • src/services/localQuickStart/dockerProbes.ts (probeDockerEndpoint)
  • src/services/localQuickStart/dockerReadinessClassification.ts

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/services/localQuickStart/DockerReadinessService.ts and src/services/localQuickStart/dockerProbes.ts, especially probeDockerEndpoint, then trace how the resolved endpoint and shared readiness deadline are used. Add the optional /_ping diagnosis without changing CLI endpoint resolution or classification semantics, and cover both Unix socket and Windows named pipe paths in tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, node.js, typescript
Domain
devops, testing-qa, tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.