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

Xav*_*ero 4 windows filesystems symlink samba docker

问题

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

语境

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

/files/repos/app-1
/files/repos/app-2
/files/repos/lib-x
/files/repos/lib-y
Run Code Online (Sandbox Code Playgroud)

两者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
Run Code Online (Sandbox Code Playgroud)

开发人员需要使用 Windows。

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

这使我们能够:

  • 从其自己的文件夹中编辑任何项目,并运行该项目的单元测试,包括运行lib-xlib-y.
  • 开发任何库并在相关应用程序中更新它们(注意我说的是 DEVEL,而不是 PRE 或 PROD)。
  • 从 IDE 中,可以看到任何应用程序(例如app-1)的“完整结构”,还可以看到 的类,lib-x因此lib-y自动完成功能可以完美地工作。

这种方式已经运行了近十年,而且效果非常好。

问题

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

去码头工人

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

实际上有什么作用

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

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

我们在Linux 容器内部和往来之间app-1建立app-2lib-x符号链接。lib-y

如果我们在本地 Docker 中运行应用程序,这确实可以完美工作,并且存储库也可以正常工作

Linux 容器和 Windows 主机中的符号链接问题

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

这使得 IDE 无法遵循 C:\repos\app-1\vendor\lib-x 并且所有代码完成帮助程序都被破坏。

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

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

我们使用 Samba 的解决方案

最初我认为,在旧的拓扑中,Linux 服务器只是通过 samba 共享文件系统,而 Windows 只能读取符号链接内容,因为它们在服务器端而不是客户端解映射,我认为我可以运行另一台 docker 机器使用 samba 服务器只是为了将“从 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
Run Code Online (Sandbox Code Playgroud)

但这是冲突的,因为 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"
Run Code Online (Sandbox Code Playgroud)

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

  • 看来该 IP 仅用于内部 docker 网络,但从主机上看不到
  • 看来原来的服务仍然不是监听 127.0.0.1:445 而是监听 0.0.0.0:445 所以仍然“阻止”附件监听 192.168.4.83:445

所以问题

我怎样才能让 Windows 主机看到“符号链接的解映射内容”,以使 IDE 看到从 docker linux 容器内部链接的供应内容?

Xav*_*ero 6

长话短说

  1. 以管理员身份运行 git-bash。
  2. export MSYS=winsymlinks:nativestrictgit-bash 中的问题。
  3. 从那时起,ln -s在 Windows 中工作。
  4. 从泊坞窗内部可以看到链接。

细节

我们将逐步完成以下步骤:

  1. 准备工作:准备一个临时目录,其中包含abc目录中的一些文件。
  2. 看看它失败:我们将尝试创建一个符号链接并看看它失败。
  3. 创建符号链接:我们将在 Windows 中创建符号链接并查看它。我们将xyz指出abc.
  4. 运行 docker:然后我们将运行 dockerubuntu并更改xyz.
  5. 检查 ubuntu 容器:abc我们还将在 docker 中看到更改。
  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
Run Code Online (Sandbox Code Playgroud)

这是一个示例会话:

准备

2. 看着它失败

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

  • 在 git-bash 中,导航到/c/tmp
  • 然后做一个符号链接xyz指向abcln -s abc xyz
  • 通过 ls-ing 看到它失败,tmp并且看到它xyz是一个常规目录。
  • 可以肯定的是,在 中创建新内容xyz并查看它是否在 中abc

尝试创建链接。它不会成为符号链接,而是创建目录的副本。

cd /c/tmp/
ln -s abc xyz
Run Code Online (Sandbox Code Playgroud)

new_bad在中创建xyz,但在 中看不到abc它。

cd xyz/
touch new_bad
cd ../abc/
ls -l
Run Code Online (Sandbox Code Playgroud)

清除错误xyz

rm -Rf xyz/
Run Code Online (Sandbox Code Playgroud)

这是一个示例会话:

失败的尝试

3. 创建符号链接

真正的东西来了。灵感来自@Slayvin在这里的回答,以及这里Git Bash shell无法创建符号链接和这里的官方git-for-windows存储库https://github.com/git-for-windows/git/pull/156

  • 首先以管理员模式打开一个新的git-bash。原因是只有管理员才能在窗口中创建链接。

管理员模式下的 git-bash

  • 成为 CLI 管理员后,导航到目标并设置此环境变量:
export MSYS=winsymlinks:nativestrict
Run Code Online (Sandbox Code Playgroud)

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

  • 正如您所期望的那样,它只是“正常的符号链接”:ln -s abc xyz

带有符号链接的 git bash

有用!!!现在下一步是在 docker 中进行测试!

注意:根据 Sebastian 的回答/sf/answers/2863999421/如果您启用了开发人员工具,您不需要成为管理员即可在 git-bash 中创建符号链接。在搜索栏中写入for developers并启用它:

找到开发工具 启用开发工具

4. 运行 docker + 5. 签入 docker

  • 不再需要具有管理员权限的 bash 。因此,我们将关闭它并重新实例化“正常”bash。
  • 在其中,使用 docker 运行 ubuntu 容器。用于-it与 ubuntu 的 bash 交互。用于winpty允许-it工作。
  • 绑定挂载/c/tmp目录,以便abcxyz都可访问。我选择将其安装到/files.
  • 从里面cd /files看,这xyz实际上是一个符号链接。
  • 创建一些新内容xyz

运行看看:

winpty docker run -it --rm --mount type=bind,source="c:\tmp",target=/files --name ubuntu-link ubuntu
cd /files/
ls -l
Run Code Online (Sandbox Code Playgroud)

创建内容:

cd xyz
echo "yeaaahh" > new_good
Run Code Online (Sandbox Code Playgroud)

检查它确实是一个符号链接abc

cd ..
cd abc/
cat new_good
Run Code Online (Sandbox Code Playgroud)

会话示例:

码头工人会话

6. 签入windows主机

  • 从码头走出来。留在 git-bash 中。
  • 再次强调:这个 git-bash不需要特权。我们必须成为管理员的唯一时刻是在 Windows 中“创建”符号链接。
  • 从非特权 bash 中进行探索,abcxyz看到我们从 docker 内部创建的内容出现在原始目录和符号链接中。

会话示例:

在此输入图像描述

最终检查

我们终于可以去古典CMD看看它是什么样子了。我们可以看到它清楚地表明它是目录的符号链接,我们还在那里看到了目标:

在此输入图像描述

点金术

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

我们可以通过在您的 Windows 主目录中编辑来设置.bashrc

编辑bashrc 设置环境变量

通过这样做,我们可以完全正常地使用 git-bash 并开始从 Windows 创建符号链接,而不会出现任何过载。

有用

警告

以这种方式创建的符号链接可以在 Windows 中工作,并且可以从 docker 内部看到。但并非相反。如果您在容器内创建符号链接,则不会在窗口中创建它们。

因此,在已安装的卷中,始终从 git-bash 设置符号链接并从容器中使用它们。如果您从容器创建它们,它们仍然可以从容器中使用。但无法在 Windows 上使用。

结论

它可以通过 git-bash 从 Linux 风味命令完全完成。只是您需要成为管理员才能创建链接并告诉 git-bash 运行时使用该功能。并且该链接需要从 Windows 完成,而不是从 ubuntu 内部完成。