docker stack deploy Fails When Run From cmd.exe on Windows with CLI v23+ · Issue #4078 · docker/cli (original) (raw)

Description

Trying to deploy a stack (docker stack deploy) when using version 23+ of the Docker CLI under a process started by Windows cmd.exe causes an error message similar to:

unexpected environment "=::=::\\"

This also affects docker stack config.

My System

The failure happens in Docker CLI 23.0.0 and 23.0.1. I'm using Windows 10 Enterprise 21H2 19044.2604.

The Key Part

cmd.exe has to be involved in starting the docker process in some manner. So you could run cmd.exe and then docker. Or cmd.exe and then pwsh.exe and then docker.

The Relevant Code

This appears to be the relevant code. Environment variables are read and iterated through. If one is found with a blank name/key, the error message is printed and docker aborts.

Why Does This Happen

The Old New Thing has the best explanation of this. cmd.exe basically keeps special environment variables with blank names to support old MS-DOS functionality. These are the environment variables that Docker stumbles over.

Stack Overflow question about this. Here you'll see talk of the =::=::\\ value that I commonly see.

Reproduce

  1. Be using the Docker CLI version 23.0.0 or 23.0.1 on Windows.
  2. Have a simple stack file named Stack.yml. See example below.
  3. Start a Windows command prompt (cmd.exe) - This is key!
  4. Run this: docker stack deploy -c Stack.yml Stack
  5. The output is:
unexpected environment "=::=::\\"

Example Stack File:

services:
  hello:
    image: hello-world:latest

Expected behavior

The stack should deploy without error.

For comparison purposes, you can follow these steps to see the stack deploy correctly:

  1. Be using the Docker CLI version 23.0.0 or 23.0.1 on Windows.
  2. Have a simple stack file named Stack.yml. See example in the Reproduce section.
  3. Start a PowerShell 7 session without going through cmd.exe. The reliable way I've found to do this is search for pwsh.exe from the Start menu. Using icons in the Start menu doesn't seem to work all the time.
  4. Run this: docker stack deploy -c Stack.yml Stack
  5. The output is:
Creating network Stack_default
Creating service Stack_hello

docker version

C:\Users\twinter>docker version Client: Version: 23.0.1 API version: 1.42 Go version: go1.19.5 Git commit: a5ee5b1 Built: Thu Feb 9 19:50:24 2023 OS/Arch: windows/amd64 Context: default

Server: Docker Engine - Community Engine: Version: 23.0.1 API version: 1.42 (minimum version 1.12) Go version: go1.19.5 Git commit: bc3805a Built: Thu Feb 9 19:46:47 2023 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.18 GitCommit: 2456e983eb9e37e47538f59ea18f2043c9a73640 runc: Version: 1.1.4 GitCommit: v1.1.4-0-g5fd4c4d docker-init: Version: 0.19.0 GitCommit: de40ad0

docker info

Client: Context: default Debug Mode: false Plugins: sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.) Version: 0.6.1 Path: C:\Users\twinter.docker\cli-plugins\docker-sbom.exe

Server: Containers: 25 Running: 0 Paused: 0 Stopped: 25 Images: 17 Server Version: 23.0.1 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Using metacopy: false Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: active NodeID: 1bis6jp8bw0eg3x73wfrq1px5 Is Manager: true ClusterID: exugqkpkx2cn5bp38wcw73dxo Managers: 1 Nodes: 1 Default Address Pool: 10.0.0.0/8 SubnetSize: 24 Data Path Port: 4789 Orchestration: Task History Retention Limit: 5 Raft: Snapshot Interval: 10000 Number of Old Snapshots to Retain: 0 Heartbeat Tick: 1 Election Tick: 10 Dispatcher: Heartbeat Period: 5 seconds CA Configuration: Expiry Duration: 3 months Force Rotate: 0 Autolock Managers: false Root Rotation In Progress: false Node Address: 10.2.96.83 Manager Addresses: 10.2.96.83:2377 Runtimes: io.containerd.runc.v2 runc Default Runtime: runc Init Binary: docker-init containerd version: 2456e983eb9e37e47538f59ea18f2043c9a73640 runc version: v1.1.4-0-g5fd4c4d init version: de40ad0 Security Options: seccomp Profile: builtin Kernel Version: 4.18.0-425.3.1.el8.x86_64 Operating System: Red Hat Enterprise Linux 8.7 (Ootpa) OSType: linux Architecture: x86_64 CPUs: 3 Total Memory: 7.071GiB Name: PRD-VIRT-RHL-56.AD.VERVEINDUSTRIAL.COM ID: IPGK:JLNH:EKXO:NZLH:O2O4:GQC5:PE7C:NYBC:BKQA:HNR2:Q36F:WCJ5 Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false

Additional Info

Checking the Environment Like Docker CLI

Below is a simple golang program that uses the Docker CLI code to show you the environment variables that are failing Docker.

package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
  buildEnvironment(os.Environ())
}

func buildEnvironment(env []string) (map[string]string, error) {

    result := make(map[string]string, len(env))
    for _, s := range env {
        k, v, ok := strings.Cut(s, "=")
        if !ok || k == "" {
            fmt.Println("unexpected environment:")
            fmt.Println("  key:  ", k)
                        fmt.Println("  value:", v)
                        fmt.Println()
        }
        // value may be set, but empty if "s" is like "K=", not "K".
        result[k] = v
    }
    return result, nil
}