apache/beam · error

couldn't connect to docker

Error message

couldn't connect to docker:%w

What it means

dockerEnvironment initializes a Docker client from the local environment (dcli.FromEnv) to launch an SDK harness container. If the Docker client cannot be constructed or connected — because Docker is absent or misconfigured — the error is wrapped as "couldn't connect to docker".

Solutions

  1. Install/start Docker and confirm `docker ps` works for the prism process user
  2. Fix DOCKER_HOST (e.g. unix:///var/run/docker.sock) in the prism environment
  3. Add the running user to the docker group or adjust socket permissions
  4. Use the process or external environment type instead of docker if no daemon is available

Example fix

// before
DOCKER_HOST=tcp://localhost:2375 prism --job ...
// after
docker system start  # or on linux: sudo systemctl start docker
DOCKER_HOST=unix:///var/run/docker.sock prism --job ...
Defensive patterns

Strategy: validation

Validate before calling

if err := exec.Command("docker", "info").Run(); err != nil {
  return fmt.Errorf("docker daemon not reachable: %w", err)
}

Try / catch

if err := job.Run(ctx); err != nil {
  var derr *dockerConnectErr
  if errors.As(err, &derr) { /* start daemon / fix DOCKER_HOST */ }
}

Prevention

When it happens

Trigger: dcli.New(dcli.FromEnv) fails when DOCKER_HOST is malformed, the Docker socket is missing, or the docker daemon is not running.

Common situations: Running prism on a host without Docker installed, DOCKER_HOST pointing to a dead remote, or missing socket permissions (user not in docker group).

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/49a4fca758fe071f. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/environments.go:174

	// This goroutine blocks until the context is cancelled, signalling
	// that the pool runner should stop the worker.
	<-ctx.Done()

	// Previous context cancelled so we need a new one
	// for this request.
	pool.StopWorker(bgContext, &fnpb.StopWorkerRequest{
		WorkerId: wk.ID,
	})
	wk.Stop()
}

func dockerEnvironment(ctx context.Context, logger *slog.Logger, dp *pipepb.DockerPayload, wk *worker.W, artifactEndpoint string) error {
	logger = logger.With("worker_id", wk.ID, "image", dp.GetContainerImage())

	// TODO consider preserving client?
	cli, err := dcli.New(dcli.FromEnv)
	if err != nil {
		return fmt.Errorf("couldn't connect to docker:%w", err)
	}

	// TODO abstract mounting cloud specific auths better.
	const gcloudCredsEnv = "GOOGLE_APPLICATION_CREDENTIALS"
	gcloudCredsFile, ok := os.LookupEnv(gcloudCredsEnv)
	var mounts []mount.Mount
	var envs []string
	if ok {
		_, err := os.Stat(gcloudCredsFile)
		// File exists
		if err == nil {
			dockerGcloudCredsFile := "/docker_cred_file.json"
			mounts = append(mounts, mount.Mount{
				Type:   "bind",
				Source: gcloudCredsFile,
				Target: dockerGcloudCredsFile,
			})
			credEnv := fmt.Sprintf("%v=%v", gcloudCredsEnv, dockerGcloudCredsFile)

View on GitHub (pinned to 12126d8942)