19

I'm trying to make an application work on Windows that's been developed only on Unices. It's all dockerized and it uses the traefik load balancer. The volumes for the docker for running traefik looks like this:

volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro,delegated
- ${PWD}/load_balancer/traefik.toml:/etc/traefik/traefik.toml:ro,delegated

The first volume works fine on Mac or Linux, but does it on Windows? The application is failing (the load balancer is giving a 404) and it might be related to that volume. When I start the image, the socket looks like a socket:

/ # ls -laF /var/run/docker.sock
srw-rw----    1 root     root             0 Sep  2 11:04 /var/run/docker.sock=

Is this working? Any way to test it? What's the correct way of doing this?

Trying to figure this out, I tried replacing it with this:

volumes:
- //./pipe/docker_engine:/var/run/docker.sock

based on various articles and bug reports I found online. The docker image starts but it fails in the same way and now in the docker container it looks like a directory:

/ # ls -laF /var/run/docker.sock
total 4
drwxr-xr-x    2 root     root            40 Sep  3 14:52 ./
drwxr-xr-x    1 root     root          4096 Sep  3 14:57 ../

Following Marc ABOUCHACRA's answers, I tried:

volumes:
- type: npipe
  source: ////./pipe/docker_engine
  target: /var/run/docker.sock
  consistency: delegated

but that also looks like a directory:

/ # ls -laF /var/run/docker.sock
total 4
drwxr-xr-x    2 root     root            40 Sep  3 14:52 ./
drwxr-xr-x    1 root     root          4096 Sep  3 14:57 ../

I also tried this:

volumes:
- npipe:////./pipe/docker_engine:/var/run/docker.sock:ro,delegated

but that fails with this error:

ERROR: Volume npipe:////./pipe/docker_engine:/var/run/docker.sock:ro,delegated has incorrect format, should be external:internal[:mode]

The whole docker-compose.yml section looks like this:

  lb:
    image: load-balancer
    build: ${WORKSPACE}/go-home/load_balancer
    ports:
    - 80:80
    - 443:443
    links:
    - wifi-ui-dev
    - wifi-ui-prod
    - portal
    - wifi-api
    env_file:
    - .env
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro,delegated
    - ${PWD}/load_balancer/traefik.toml:/etc/traefik/traefik.toml:ro,delegated

My question is specifically about running this docker image, which is a Linux, on a Windows host, running Docker for Windows. I understand that I can run it on a Linux host by installing Linux on another machine or a VM on the Windows machine, it's equivalent. Running Windows guests is not what I'm after either in case there's a way of exposing sockets from Windows to Windows only.

Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • Does this help? https://github.com/docker/for-win/issues/1829, https://github.com/MicrosoftDocs/Virtualization-Documentation/issues/442 – Tarun Lalwani Aug 18 '19 at 16:57
  • @TarunLalwani: that's where I learned about /pipe/docker_engine, but neither link mentions `volumes:`, so, I'm not sure what the syntax is. That syntax doesn't crash, but I'm not sure if it works either (the docker image is not working, but I don't know if that's related to the socket or something else by now). – Pablo Fernandez Aug 19 '19 at 05:48
  • 1
    https://stackoverflow.com/questions/36765138/bind-to-docker-socket-on-windows – LinPy Aug 19 '19 at 08:32
  • can you provide the whole docker file so that we can try to figure out? – arnonuem Aug 19 '19 at 11:27
  • 1
    I think the terminology is misleading - you _bind_ a socket and _mount_ a volume. Are you trying to mount a volume ? Binding to a docker socket might be needed for very niche tasks such as managing docker daemon from container as part of a CI/CD pipeline tooling for example. If you are mounting a volume and specifically you are trying to access host's directory from the container then there are several ways to do that on Windows. Easiest one is through WSL? then you can keep all your compose/dockerfiles as is. If you can't, then you can use windows paths from powershell, but you'd have to shar – EvgeniySharapov Aug 20 '19 at 02:06
  • @arnonuem is that what you wanted? I wasn't sure. – Pablo Fernandez Aug 20 '19 at 09:08
  • @LinPy: yeah, I've seen various examples of specifying sockets in Windows on the command line, but none specifying it in the docker-compose file. – Pablo Fernandez Aug 20 '19 at 09:10

5 Answers5

15

If you cannot nor want use network sockets, then you can use named pipes. The syntax depends whether you run Linux or Windows containers and on the shell you use.

Linux containers

If you run Linux containers on a Windows machine, this seems to work using Powershell or bash:

docker run --rm -it -v "//var/run/docker.sock://var/run/docker.sock" image_with_docker docker version

Please note the extra / in front of /var/run/docker.sock, both for the source and destination volumes.

Windows containers

If you run Windows containers on a Windows machine, this seems to work using Powershell or bash:

docker run -v "//./pipe/docker_engine://./pipe/docker_engine" --rm -it image-with-docker docker version

Note that this works only in Powershell:

docker run -v "\\.\pipe\docker_engine:\\.\pipe\docker_engine" --rm -it image-with-docker docker version

Therefore, it's better to use the version with /.

Extra - docker-compose.yml

If you use a docker-compose.yaml file, this works with Windows containers.

version: '3.7'

services:
  docker:
    image: image-with-docker
    command:
      - docker
      - version
    volumes:
      - type: npipe
        source: \\.\pipe\docker_engine
        target: \\.\pipe\docker_engine

With Linux containers, you can use the shortened form:

  docker:
    image: image-with-docker
    command:
      - docker
      - version
    volumes:
      - //var/run/docker.sock://var/run/docker.sock

Extra - Kubernetes

If you are running Windows containers on a Windows node in Kubernetes, this seems to work:

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: docker
      image: image-with-docker
      command:
        - powershell
      args:
        - Start-Sleep
        - "999999"
      volumeMounts:
        - mountPath: \\.\pipe\docker_engine
          name: dockersock
  volumes:
    - name: dockersock
      hostPath:
        path: \\.\pipe\docker_engine
        type: null
  nodeSelector:
    kubernetes.io/os: windows

In this case, beside using the \, please note the type: null in the definition of the dockersock volume: if you don't set it, it will not work.

Notes

Everything was tested on docker 19.03 and on Kubernetes 1.18.

Client:
 Version:           19.03.3
 API version:       1.40
 Go version:        go1.12.10
 Git commit:        2355349d-
 Built:             10/14/2019 16:41:26
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.24)
  Go version:       go1.12.17
  Git commit:       afacb8b
  Built:            Wed Mar 11 01:37:20 2020
  OS/Arch:          windows/amd64
  Experimental:     false
Fabio
  • 491
  • 3
  • 10
  • Cannot create container for service traefik: invalid mount config for type "npipe": mount type unknown – aswzen Jan 13 '22 at 07:51
5

If you encounter the following error on windows:

cannot create container for service portainer: Unrecognised volume spec: file '\.\pipe\docker_engine' cannot be mapped. Only directories can be mapped on this platform ERROR: Encountered errors while bringing up the project.

Try adding an extra slash to it, resulting in following volumes section:

volumes:
  - source: \\.\pipe\docker_engine\
    target: \\.\pipe\docker_engine\
    type: npipe

Tested with compose 3.7 and docker CE 19.03.12

Sven Hakvoort
  • 3,543
  • 2
  • 17
  • 34
1

Using short syntax with the type of the bind mount is not possible : npipe:////./pipe/docker_engine:/var/run/docker.sock:ro,delegated

You need to use the long syntax in your compose file :

volumes:
  - type: npipe
    source: ////./pipe/docker_engine
    target: /var/run/docker.sock
    consistency: delegated

You can find some documentation about the long syntax in the official documentation. This syntaxe is from v3.2

Also keep in mind what @lucas-ramage said about using windows container only when using npipe.

Marc ABOUCHACRA
  • 3,155
  • 12
  • 19
  • So, npipe only works when the guest is a Windows docker image? – Pablo Fernandez Aug 26 '19 at 07:38
  • Yes (at least, that's what the documentation is saying). If you are on Docker for Windows, then you should either use **npipe** (works only with windows container), or you can connect through a **TCP socket**. You can find the *(really light)* doc [here](https://docs.docker.com/docker-for-windows/faqs/#how-do-i-connect-to-the-remote-docker-engine-api) – Marc ABOUCHACRA Aug 27 '19 at 08:10
  • When I use this solution, the socket looks like a folder inside the Docker container. I updated the question with the relevant information. – Pablo Fernandez Sep 03 '19 at 15:05
1

In 2022, on Windows 11, what worked for me is below volume configuration (Note the doube slash (//) on the host side of configruation. Not sure why docker_enginer variant does not work for me.

-v "//var/run/docker.sock:/var/run/docker.sock"
PravyNandas
  • 607
  • 11
  • 12
  • can confirm this works on Win 10 too, I think it has more to do with using WSL 2 backend than the OS version – Sebastian Jan 05 '23 at 21:58
0

Per the Docker for Windows FAQ,

On Docker Desktop for Windows, clients can connect to the Docker Engine through a named pipe: npipe:////./pipe/docker_engine

See also this issue on GitHub,

The windows version of docker doesn't use unix socket (/var/run/docker.sock) but npipe (npipe:////./pipe/docker_engine). So you have either

  • to switch to linux container which runs docker in a full virtualized linux with unix socket
  • to pass the npipe instead of the unix socket to the container (windows container only)
  • to use a network socket (should work with linux and windows container)

However, since this is a Linux container, your options are either A) Run docker in a virtual machine (first choice above), or B) Use a network socket (the third choice).

Community
  • 1
  • 1
oxr463
  • 1,573
  • 3
  • 14
  • 34
  • 1
    Thank you for the answer. I did try to pass the named pipe and it doesn't work. Docker doesn't like that syntax and I'm not sure what the right syntax is. I don't know how to achieve the same with a network socket. Any ideas? – Pablo Fernandez Aug 22 '19 at 08:35