docker/cli · error

flag --use-api-socket can't be used with a Windows Docker…

Error message

flag --use-api-socket can't be used with a Windows Docker Engine

What it means

Returned when the experimental --use-api-socket flag is combined with a Docker Engine whose OSType is "windows" (create.go:253-255). The flag bind-mounts /var/run/docker.sock and injects credentials via a Linux path scheme, neither of which exists on a Windows engine. The check fires before any container-creation side effects.

Solutions

  1. Remove the --use-api-socket flag when targeting a Windows engine.
  2. Switch Docker Desktop / the daemon to Linux containers (Linux engine) before using --use-api-socket.
  3. If you need Docker API access inside a Windows container, manually bind the Windows named pipe (//./pipe/docker_engine) instead.

Example fix

// before
docker run --use-api-socket myimage
// after (on a Windows engine)
docker run myimage
Defensive patterns

Strategy: validation

Validate before calling

// Before calling create/run with --use-api-socket, check the engine OS.
info, err := cli.Client().ServerInfo(ctx)
if err != nil { return err }
if opts.useAPISocket && info.OSType == "windows" {
    return errors.New("--use-api-socket requires a Linux engine")
}

Prevention

When it happens

Trigger: Running `docker run --use-api-socket <img>` or `docker create --use-api-socket <img>` while the connected daemon reports ServerInfo().OSType == "windows" (e.g. Docker Desktop on Windows targeting a Windows container engine, or DOCKER_HOST pointing at a Windows daemon).

Common situations: Switching Docker Desktop between Linux and Windows container modes and forgetting --use-api-socket is Linux-only; CI pipelines that set DOCKER_HOST to a remote Windows engine; scripts copied from a Linux dev box to a Windows host.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/2144e91fe98ec219. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/container/create.go:254

	ref, err := reference.ParseAnyReference(config.Image)
	if err != nil {
		return "", err
	}
	if named, ok := ref.(reference.Named); ok {
		namedRef = reference.TagNameOnly(named)
	}

	const dockerConfigPathInContainer = "/run/secrets/docker/config.json"
	var apiSocketCreds map[string]types.AuthConfig

	if options.useAPISocket {
		// We'll create two new mounts to handle this flag:
		//
		// 1. Mount the actual docker socket.
		// 2. A synthesized ~/.docker/config.json with resolved tokens.

		if dockerCLI.ServerInfo().OSType == "windows" {
			return "", errors.New("flag --use-api-socket can't be used with a Windows Docker Engine")
		}

		// hard-code engine socket path until https://github.com/moby/moby/pull/43459 gives us a discovery mechanism
		containerCfg.HostConfig.Mounts = append(containerCfg.HostConfig.Mounts, mount.Mount{
			Type:        mount.TypeBind,
			Source:      "/var/run/docker.sock",
			Target:      "/var/run/docker.sock",
			BindOptions: &mount.BindOptions{},
		})

		/*

		   Ideally, we'd like to copy the config into a tmpfs but unfortunately,
		   the mounts won't be in place until we start the container. This can
		   leave around the config if the container doesn't get deleted.

		   We are using the most compose-secret-compatible approach,
		   which is implemented at

View on GitHub (pinned to 4f84911bfe)