如何在Windows上挂载Docker Socket?

19

我正在尝试让一个只在类Unix系统开发过的应用程序在Windows上运行。它已经被容器化并使用traefik负载均衡器。运行traefik的Docker卷看起来像这样:

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

第一卷在Mac或Linux上运行良好,但在Windows上呢?应用程序失败(负载均衡器返回404错误),可能与该卷有关。当我启动镜像时,套接字看起来像一个套接字:

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

这个能用吗?有什么测试方法吗?正确的做法是什么?

试着弄明白这个问题,我试着用这个替换它:

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

根据我在网上发现的各种文章和错误报告,Docker镜像启动了,但以同样的方式失败,并且现在在Docker容器中它看起来像一个目录:

/ # 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 ../

跟随 Marc ABOUCHACRA 的回答,我尝试了:

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

但是那看起来也像一个目录:

/ # 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 ../

我也尝试了这个:

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

但是这会导致以下错误:

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

整个docker-compose.yml部分如下所示:

  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

我的问题是关于在运行Windows的Docker for Windows主机上运行Linux Docker映像。我知道我可以在另一台机器上安装Linux或在Windows机器上安装虚拟机来运行它,这是等效的。我也不想运行Windows guests,以防有一种方法可以将Windows套接字暴露给仅限Windows。


这个有帮助吗?https://github.com/docker/for-win/issues/1829,https://github.com/MicrosoftDocs/Virtualization-Documentation/issues/442 - Tarun Lalwani
1
https://dev59.com/uFoV5IYBdhLWcg3wCrLH - LinPy
1
我认为术语有误导性——你“绑定”一个套接字,而“挂载”一个卷。你是想要挂载一个卷吗?例如,在CI/CD流水线工具的一部分中,可能需要绑定到docker套接字以管理容器中的docker守护程序等非常专业的任务。如果您正在挂载一个卷,并且特别是您正在尝试从容器访问主机目录,则在Windows上有几种方法可以实现这一点。最简单的方法是通过WSL,然后您可以保留所有的compose/dockerfiles。如果您不能使用WSL,则可以从powershell使用Windows路径,但您必须共享该目录。 - EvgeniySharapov
@arnonuem 这是你想要的吗?我不太确定。 - pupeno
@LinPy:是啊,我看过在Windows上通过命令行指定套接字的各种例子,但没有在docker-compose文件中指定的例子。 - pupeno
显示剩余2条评论
5个回答

16

如果您不能或不想使用网络套接字,则可以使用命名管道。语法取决于您运行的是Linux容器还是Windows容器以及您使用的shell。

Linux容器

如果您在Windows机器上运行Linux容器,则似乎可以使用Powershell或bash来实现:

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

请注意源卷和目标卷前面都有额外的/,例如:/var/run/docker.sock

Windows容器

如果在Windows机器上运行Windows容器,则似乎可以使用PowerShell或Bash来运行:

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

请注意,这仅适用于PowerShell:

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

因此,最好使用带有/的版本。

额外 - docker-compose.yml

如果您使用docker-compose.yaml文件,则可以与Windows容器一起使用。

version: '3.7'

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

使用 Linux 容器时,您可以使用简写形式:

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

额外 - Kubernetes

如果您在Kubernetes中的Windows节点上运行Windows容器,则似乎可以这样做:

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

在这种情况下,除了使用\之外,请注意dockersock卷定义中的type: null:如果您不设置它,则不起作用。

注释

所有内容都在docker 19.03和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

无法为Traefik服务创建容器:类型为“npipe”的挂载配置无效:未知的挂载类型。 - aswzen
在 Windows 机器上使用 Linux 容器时出现了 bash: docker: command not found 的错误提示。 - undefined

5
如果您在Windows上遇到以下错误:

无法为服务portainer创建容器:未识别的卷规范:文件“\.\pipe\docker_engine”无法映射。该平台只能映射目录。 错误:启动项目时遇到错误。

请尝试在其后添加一个额外的斜杠,形成以下卷部分:
volumes:
  - source: \\.\pipe\docker_engine\
    target: \\.\pipe\docker_engine\
    type: npipe

测试使用的Compose版本为3.7,Docker CE版本为19.03.12


非常感谢!终于让我的容器运行起来了 :) - Kimberley

1

在2022年的Windows 11上,对于我而言有效的是以下音量配置(请注意配置中主机端的双斜杠(//)。不确定为什么docker_enginer变体对我无效。

-v "//var/run/docker.sock:/var/run/docker.sock"

可以确认这也适用于Win 10,我认为这更多与使用WSL 2后端有关,而不是操作系统版本。 - Sebastian

1

使用绑定挂载的类型时,无法使用简短语法:npipe:////./pipe/docker_engine:/var/run/docker.sock:ro,delegated

您需要在compose文件中使用长语法:

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

你可以在官方文档中找到一些关于长语法的文档。这种语法是从v3.2开始的。
还要记住@lucas-ramage所说的,在使用npipe时只使用Windows容器。

那么,npipe 只在客户机是 Windows Docker 镜像时才能工作? - pupeno
是的(至少文档是这么说的)。如果您使用的是Docker for Windows,则应该使用npipe(仅适用于Windows容器),或者可以通过TCP套接字连接。您可以在此处找到*(非常轻巧的)*文档链接 - Marc ABOUCHACRA
当我使用这个解决方案时,套接字看起来像是Docker容器内的一个文件夹。我已经更新了相关信息的问题。 - pupeno

0
根据Docker for Windows FAQ

在Docker Desktop for Windows上,客户端可以通过命名管道连接到Docker Engine:npipe:////./pipe/docker_engine

另请参阅GitHub上的问题,

Docker的Windows版本不使用Unix套接字(/var/run/docker.sock),而是使用npipe(npipe:////./pipe/docker_engine)。所以你要么

  • 切换到运行完全虚拟化Linux的Linux容器中的Docker,其中包含Unix套接字
  • 将npipe传递给容器而不是Unix套接字(仅适用于Windows容器)
  • 使用网络套接字(应该适用于Linux和Windows容器)

然而,由于这是一个 Linux 容器,您的选择要么是 A) 在虚拟机中运行 Docker(上面的第一选择),要么是 B) 使用网络套接字(第三个选择)。


1
谢谢您的回答。我尝试传递命名管道,但它不起作用。Docker不喜欢那种语法,我也不确定正确的语法是什么。我不知道如何使用网络套接字实现相同的功能。有什么想法吗? - pupeno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接