Skip to content

WSL2: restart-policy containers start before the WSL bind-mount proxy is ready (file mounts fail with "not a directory", directory mounts are empty) #731

Open

Description

@sliva-name

Bug description

On a cold start of Docker Desktop (WSL2 backend), dockerd starts containers that have restart: unless-stopped before the WSL integration proxy (docker-desktop-user-distro proxy) has populated /mnt/wsl/docker-desktop-bind-mounts/<distro>/. Every container with a bind mount from the integrated distro is affected:

  • Single-file bind mount: the container does not start. Exited (127), and State.Error is:
    failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/run/desktop/mnt/host/wsl/docker-desktop-bind-mounts/Ubuntu/<hash>" to rootfs at "/etc/clickhouse-server/config.d/load.xml": ... not a directory: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
    
    RestartCount stays 0: the restart policy never retries, because the task was never created. The container stays down until it is started manually.
  • Directory bind mount: the container starts and even reports healthy, but the mount target is an empty directory. In our case nginx returned 404 from an empty /var/www, and two consumers saw an empty data directory. This silent variant is worse than the hard failure.

docker restart <container> fixes both without any config change. The source files and directories in the distro are intact the whole time.

Whether the WSL distro is cold or warm decides the outcome. Running Docker Desktop as administrator makes no difference (tested both ways):

  • After wsl --shutdown, the first Docker Desktop start always breaks.
  • Quitting Docker Desktop and starting it again while the distro is still running always works.

Environment

  • Windows 10.0.26300.9550
  • WSL 3.0.1.0, kernel 6.18.40.1
  • Docker Desktop 4.94.0 (241994), Engine 29.8.2, WSL2 backend
  • Integrated distro: Ubuntu 26.04.1 LTS with [boot] systemd=true in /etc/wsl.conf
  • Compose projects live in the distro filesystem (/home/<user>/...), and their services use restart: unless-stopped

Timeline from the logs

Sources: %LOCALAPPDATA%\Docker\log\host\com.docker.backend.exe.log* and %LOCALAPPDATA%\Docker\log\vm\init.log*.

  • Proxy mounted: the first docker-desktop-user-distro.apiproxy ... mounting /home/... to /mnt/wsl/docker-desktop-bind-mounts/Ubuntu/<hash> line.
  • First container start: the first not a directory error, or, when nothing failed, the earliest State.StartedAt among bind-mounted containers.
Start (UTC) WSL state First container start Proxy mounted Result
20:00:54 cold (after wsl --shutdown) 20:01:00.440 20:01:01.995 proxy 1.55 s late, failures
20:02:29 cold 20:02:34.414 20:02:36.335 proxy 1.92 s late, failures
20:03:48 cold 20:03:53.299 20:03:54.489 proxy 1.19 s late, failures
19:56:24 warm (Desktop quit and started again) 19:56:27.091 19:56:26.804 proxy 0.29 s ahead, OK
20:04:11 warm 20:04:14.442 20:04:14.127 proxy 0.31 s ahead, OK

Overall: 5 of 5 cold starts failed and 4 of 4 warm starts succeeded that evening. On the warm starts the proxy wins by only ~0.3 s, so every start is a race.

On a cold start the extra time goes to the distro boot:

  • start wsl integration for distro Ubuntu is logged ~3 s after starting engine linux/wsl, vs ~1.2 s on a warm start.
  • The first wsl.exe -d Ubuntu -e cat /etc/wsl.conf takes 2.1 s (distro boot with systemd), vs ~0.1 s on a warm start.
  • Whatever the integration state, dockerd starts restart-policy containers ~5 s after starting engine linux/wsl.

Reproduction steps

  1. In the integrated WSL distro (in its own filesystem, not under /mnt/c), create a project:
    mkdir -p ~/bind-race/data && cd ~/bind-race
    echo hello > app.conf
    touch data/file.txt
    compose.yaml:
    services:
      file-mount:
        image: alpine:3.22
        restart: unless-stopped
        command: ["sh", "-c", "cat /config/app.conf && sleep infinity"]
        volumes:
          - ./app.conf:/config/app.conf:ro
      dir-mount:
        image: alpine:3.22
        restart: unless-stopped
        command: ["sh", "-c", "ls -A /data && sleep infinity"]
        volumes:
          - ./data:/data:ro
  2. Run docker compose up -d and check that both containers are running and that docker compose exec dir-mount ls -A /data shows file.txt.
  3. Quit Docker Desktop from the tray, then run wsl --shutdown in PowerShell.
  4. Start Docker Desktop. Do not open the distro beforehand.
  5. Check the containers:
    • file-mount is Exited (127), and docker inspect -f '{{.State.Error}}' bind-race-file-mount-1 shows the not a directory error.
    • dir-mount is Up, but docker compose exec dir-mount ls -A /data is empty.
  6. Quit Docker Desktop and start it again without wsl --shutdown. Both containers now come up correctly.

Expected behavior

At engine startup, containers whose bind sources come from an integrated WSL distro should not be started until the integration proxy for that distro is ready. Alternatively, Docker Desktop could retry a failed restart-policy start once the proxy is ready.

Workaround

After Docker Desktop is up, restart every container that has a bind mount from the distro (docker restart ... or docker compose up -d --force-recreate).

Related

#601 (same symptoms after a Windows reboot, open since 2024) and #176 (same not a directory error with unless-stopped). This report adds the timing evidence and the cold-vs-warm determinism.

Поле: Platform

Windows

Client:
 Version:           29.8.2
 API version:       1.56
 Go version:        go1.26.8
 Git commit:        7fc2dff
 Built:             Wed Sep 30 19:31:45 2026
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Desktop 4.94.0 (241994)
 Engine:
  Version:          29.8.2
  API version:      1.56 (minimum version 1.40)
  Go version:       go1.26.8
  Git commit:       8af9fe3
  Built:            Wed Sep 30 19:32:25 2026
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v2.3.6
  GitCommit:        ee2735368117d2eb259779949d5e75cdafec9761
 runc:
  Version:          1.5.1
  GitCommit:        v1.5.1-0-g8f2685a4
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
Client:
 Version:    29.8.2
 Context:    default
 Debug Mode: false
 Plugins:
  agent: Docker AI Agent Runner (Docker Inc.)
    Version:  v1.144.0
    Path:     /usr/local/lib/docker/cli-plugins/docker-agent
  ai: Docker AI Agent - Ask Gordon (Docker Inc.)
    Version:  v1.31.0
    Path:     /usr/local/lib/docker/cli-plugins/docker-ai
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.37.2
    Path:     /usr/local/lib/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v5.5.1
    Path:     /usr/local/lib/docker/cli-plugins/docker-compose
  debug: Get a shell into any image or container (Docker Inc.)
    Version:  0.0.47
    Path:     /usr/local/lib/docker/cli-plugins/docker-debug
  desktop: Docker Desktop commands (Docker Inc.)
    Version:  v0.4.4
    Path:     /usr/local/lib/docker/cli-plugins/docker-desktop
  dhi: CLI for managing Docker Hardened Images (Docker Inc.)
    Version:  v0.0.7
    Path:     /usr/local/lib/docker/cli-plugins/docker-dhi
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.31
    Path:     /usr/local/lib/docker/cli-plugins/docker-extension
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v1.4.0
    Path:     /usr/local/lib/docker/cli-plugins/docker-init
  mcp: Docker MCP Plugin (Docker Inc.)
    Version:  v0.44.1
    Path:     /usr/local/lib/docker/cli-plugins/docker-mcp
  model: Docker Model Runner (Docker Inc.)
    Version:  v1.2.6
    Path:     /usr/local/lib/docker/cli-plugins/docker-model
  offload: Docker Offload (Docker Inc.)
    Version:  v0.6.53
    Path:     /usr/local/lib/docker/cli-plugins/docker-offload
  pass: Docker Pass Secrets Manager Plugin (beta) (Docker Inc.)
    Version:  v0.2.4
    Path:     /usr/local/lib/docker/cli-plugins/docker-pass
  sandbox: "docker sandbox" is deprecated, use Docker Sandboxes instead (Docker Inc.)
    Version:  v0.13.0
    Path:     /usr/local/lib/docker/cli-plugins/docker-sandbox
  scout: Docker Scout (Docker Inc.)
    Version:  v1.25.0
    Path:     /usr/local/lib/docker/cli-plugins/docker-scout

Server:
 Containers: 36
  Running: 26
  Paused: 0
  Stopped: 10
 Images: 44
 Server Version: 29.8.2
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: local
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Discovered Devices:
  cdi: docker.com/gpu=webgpu
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 nvidia runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: ee2735368117d2eb259779949d5e75cdafec9761
 runc version: v1.5.1-0-g8f2685a4
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.18.40.1-microsoft-standard-WSL2
 Operating System: Docker Desktop (containerized)
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 15.18GiB
 Name: docker-desktop
 ID: <redacted>
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Labels:
  com.docker.desktop.address=unix:///var/run/docker-cli.sock
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5555
  127.0.0.0/8
  ::1/128
 Live Restore Enabled: false
 Firewall Backend: iptables

Activity

  1. added theissue type on Oct 6, 2026
  2. changed the title [-]Контейнеры с restart policy стартуют раньше, чем готов прокси для монтирования из WSL.[/-] [+]WSL2: restart-policy containers start before the WSL bind-mount proxy is ready (file mounts fail with "not a directory", directory mounts are empty)[/+] on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions