我怎样才能使从 docker linux 容器内部创建的符号链接可以从 windows 主机看到(如果需要,可能涉及 samba)

How can I make symlinks made from inside docker linux containers to be seen from a windows host (maybe involving samba, if needed)

问题

如何从 windows 主机中查看 docker linux 容器的符号链接? (即使我必须放置一个中间 linux 机器通过 NFS 或 Samba 公开文件系统)

上下文

在 DEVEL 环境中,我在办公室的 Linux 中的某个远程文件系统中有这个结构:

/files/repos/app-1
/files/repos/app-2
/files/repos/lib-x
/files/repos/lib-y

app-1app-2 都使用像这样出售和符号链接的库:

/files/repos/app-1/vendor/my-company/lib-x => /files/repos/lib-x
/files/repos/app-1/vendor/my-company/lib-y => /files/repos/lib-y
/files/repos/app-2/vendor/my-company/lib-x => /files/repos/lib-x
/files/repos/app-2/vendor/my-company/lib-y => /files/repos/lib-y

开发人员需要在 Windows.

因此开发人员将他们的 IDE 指向某个已安装的单元,例如 Z:\ 他们可以在其中看到所有的存储库和项目。

这使我们能够:

这已经这样工作了将近十年并且完美无缺。

问题

开发人员需要连接到服务器才能进行开发,我们希望转变为本地 dockers,这样我们就可以让开发人员在家工作。

要去docker

我们现在决定不再使用办公室服务器,我们将在 docker 个容器中设置所有开发。

什么才是真正有效的

我们刚刚在 Windows 中安装了 docker 桌面,并将主机中的 C:\repos 共享到 docker 中。

我们现在有一些开发机器 FROM ubuntu:xxx 和 运行 它们正在安装卷。

我们从 linux 容器中将 app-1app-2 中的符号链接指向 lib-xlib-y

如果我们 运行 本地 dockers

中的应用程序,这确实工作得很好,而且存储库工作得很好

linux 容器和 windows 主机中的符号链接有问题

现在的问题是 IDE:当它读取 C:\repos\app-1 中的文件时,在 linux 容器中创建的符号链接无法从主持人。

这使得 IDE 无法跟随 C:\repos\app-1\vendor\lib-x 并且所有代码完成助手都被破坏了。

我已经知道 Windows 不支持与 linux 符号链接兼容的符号链接。

这迫使我们寻找替代解决方案。

我们使用 Samba 的解决方案

最初我认为与旧拓扑一样,linux 服务器只是通过 samba 共享文件系统,windows 可以读取符号链接内容,因为它们在服务器端被解映射并且不是客户端,我认为我可以 运行 另一台带有 samba 服务器的 docker 机器只是为了再次在本地共享 "things seen from the linux" 到 Windows 主机。

为此,我设置了这个 docker-compose:

version: "3.7"
services:
    samba:
        container_name: samba
        hostname: samba
        image: dperson/samba
        volumes:
            - //c/Users/xavi/Documents/repos/test_samba:/mount
        ports:
            - "139:139"
            - "445:445"
        command: samba.sh -s "test_samba;/mnt/repos/test_samba;yes;no;yes;all"
        restart: always

但这会产生冲突,因为 445 已在本地使用。

如果我关闭本地 SMB,那么在下次重新启动时,docker 无法将 C:\ 共享到 docker(我没有意识到它通过 SMB 进行共享,可以它会变成 NFS 左右吗?)

如果我映射到另一个端口,比如 10445:445 那么客户端将无法访问它,因为 windows 中的客户端 samba 端口似乎不可配置。

映射 IP

所以我尝试映射一个IP:

version: "3.7"
services:
    samba:
        container_name: samba
        hostname: samba
        image: dperson/samba
        volumes:
            - //c/Users/xavi/Documents/repos/test_samba:/mount
        ports:
            - "139:139"
            - "192.168.4.83:445:445"
        command: samba.sh -s "test_samba;/mnt/repos/test_samba;yes;no;yes;all"
        restart: always
        networks:
            samba:
                ipv4_address: 192.168.4.83
networks:
    samba:
        ipam:
            driver: default
            config:
                -   subnet: "192.168.4.0/16"

但似乎这仍然会产生问题:

所以问题

如何让 windows 主机看到 "demapped contents of symlinks" 让 IDE 看到从 docker [=142= 内部链接的销售内容] 集装箱?

我在设置时遇到了类似的问题:在 Windows 10 上开发(IDE 和 Docker 都是 运行),并且网站 运行 容器内 (Linux).

我曾经在网站需要的库上工作,同时处理两个项目。为此,库目录在供应商路径中被符号链接(在 host/Windows 中)。

类似于:

+ my-website  
  ↪ vendor  
    ↪ company  
      ↪ my-package (->symlink here)
  ↪ ...
  ↪ docker-compose.yml

+ external-packages  
  ↪ company  
    ↪ my-package (real files here)

但是对于 Docker,该设置不再有效。 所以诀窍是在 docker-compose 中安装一个卷,如下所示:

volumes:
  - ./:/my-app 
  - ../external-packages/company:/my-app/vendor/company

因此 vendor 中的文件是 Web 服务器(在容器内)'seen',我们可以保留 [=12] 之间的符号链接(在 windows 中创建) =] 文件夹,所以 IDE 也能看到它们。

希望对您有所帮助。

TL;DR

  1. 运行 git-bash 作为管理员。
  2. 在 git-bash 中发布 export MSYS=winsymlinks:nativestrict
  3. 从那时起,ls -s 在 windows 工作。
  4. 从 docker.
  5. 内部可以看到链接

详情

我们将完成这些步骤:

  1. 准备:准备一个临时目录,其中包含 abc 目录中的一些文件。
  2. 看到它失败了:我们将尝试制作一个 symlink 并看到它失败。
  3. Create symlink: 我们将在 windows 中创建 symlink 并查看它。我们将 xyz 指向 abc
  4. 运行 docker: 然后我们将 运行 docker 和 ubuntu 更改内容xyz.
  5. 签入 ubuntu 容器: 我们也会在 docker.[=210= 中看到 abc 中的更改]
  6. 签入 windows 主机: 那么从容器外检查 abcxyz

1。准备

  • 在 git-bash 中转到 /c 并创建一个临时目录 tmp
  • 在其中创建一个 abc 目录并在其中添加一些内容。
cd /c
mkdir tmp
cd tmp/
mkdir abc
cd abc/
echo 1111 > old_1
echo 2222 > old_2
echo 3333 > old_3

这是一个示例会话:

2。看到它失败

首先让我们尝试“正常”方式,看看它是否失败。

  • 在 git-bash 中,导航至 /c/tmp
  • 然后做一个 symlink 让 xyz 指向 abc: ln -s abc xyz
  • 看到它失败了,通过ls-ing tmp并且看到xyz是一个普通的目录。
  • 可以肯定的是,在 xyz 中创建新内容并在 abc 中看到 而不是

尝试创建 link(不起作用)

cd /c/tmp/
ln -s abc xyz

xyz中创建new_bad并且不要abc中看到它。

cd xyz/
touch new_bad
cd ../abc/
ls -l

清除错误xyz

rm -Rf xyz/

这是一个示例会话:

3。创建 symlink

真正的东西来了。灵感来自@Slayvin 在这里的回答,以及这里 Git Bash Shell fails to create symbolic links and the official git-for-windows repo here https://github.com/git-for-windows/git/pull/156

  • 首先在管理员模式下打开一个新的git-bash。原因是只有管理员可以在 windows.
  • 中创建 links

  • 成为 CLI 管理员后,导航至目标并设置此环境变量:
export MSYS=winsymlinks:nativestrict

这将告诉 git-bash 的 运行time 子系统实际使用 symlinks 功能。因为我们是管理员,所以我们会成功。

  • 如您所料,只是“正常符号links”:ls -s abc xyz

有效!!!现在下一步是在 docker!

内进行测试

注意:根据塞巴斯蒂安在这里的回答,您不需要成为管理员才能在git-bash中创建symlinks如果您启用了开发人员工具。在 search-bar 中写入 for developers 并启用它:

4。 运行 docker + 5.签到docker

  • 不再需要具有管理员权限的 bash 。所以我们将关闭它并 re-instantiate 一个“正常” bash.
  • 其中,运行 一个 ubuntu 容器 docker。使用 -it 与 ubuntu 的 bash 互动。使用 winpty 允许 -it 工作。
  • Bind-mount /c/tmp 目录,因此 abcxyz 都可以访问。我选择挂载到 /files.
  • 从内部看,cd /files 看到 xyz 实际上是一个符号 link。
  • xyz
  • 中创建一些新内容

运行 并查看:

winpty docker run -it --rm --mount type=bind,source="c:\tmp",target=/files --name ubuntu-link ubuntu
cd /files/
ls -l

创建内容:

cd xyz
echo "yeaaahh" > new_good

通过转到 abc:

来检查它是否真的是一个符号link
cd ..
cd abc/
cat new_good

示例会话:

6.签入 windows 主机

  • 走出docker。留在git-bash.
  • 再次声明:此 git-bash 不需要 特权。我们必须成为管理员的唯一时刻是在 windows.
  • 中“创建”symlink
  • 从无权限的 bash 中,探索 abcxyz 并看到我们从 docker 中创建的内容,出现在原始文件中目录和 symlink.

示例会话:

最终检查

我们终于可以去经典的CMD看看它长什么样了。我们可以看到它清楚地表明它是一个目录的 symlink,我们也在那里看到了目标:

点金术

如果您如上所述激活了“开发者工具”,唯一缺少的就是 ENV VAR。

我们可以通过编辑您 windows 家的 .bashrc 来设置:

通过这样做,我们可以完全正常地使用 git-bash 并开始从 windows 创建 symlinks 而无需任何重载。

注意

以这种方式创建的 symlinks 从 windows 和一个从内部看到的 e docker。但不是相反。如果您在容器内创建 symlinks,它们不会在 windows.

中创建

因此,在安装的卷中,始终从 git-bash 设置 symlinks 并从容器中使用它们。如果您从容器中创建它们,它们仍然 可以从容器中使用。但是从 windows.

开始将不可用

结论

可以通过 git-bash 从 linux 风味命令完全完成。只是您需要成为管理员才能创建 link 并告知 git-bash 运行 使用该功能的时间。 link 需要从 windows 完成,而不是从 ubuntu.

内部完成