搬砖时的一个小小发现。
背景
前段时间在 更新网站的代码,众所周知,本站是基于 Docker 配置的开发环境。然而 Docker 是基于 Linux 的,楼主不想另外搞虚拟机跑 Docker,所以升级了专业版 Windows,装了 Docker Desktop,然后跑起了 0xffff-one/0xffff-env 的 Docker 环境。
0xffff-one/0xffff-flarum 这个项目需要用 Composer 安装依赖,部分的依赖因为本地有魔改,composer
会通过创建软链接的方式来让 PHP 加载到魔改后的部分。
因为要在本地开发,0xffff-env 的 Docker 镜像要通过 Volume 的方式挂载本地的 0xffff-flarum 的代码。然后问题来了,最早我是在 wsl
用的 composer,操作类似:
ln -s xxxx yyyy
创建的软链接只能在 wsl 访问,Docker 容器里面并不能正确读取这个软链接,在 Windows 宿主机看这个软链也不没有生效,表现为一个空文件。
尝试在 PowerShell 下装 composer 和 PHP,这时候创建的是 Windows 下的软链接,类似:
New-Item -ItemType SymbolicLink -Path xxx -Value xxxx
回到 Docker 还是不行。实在没办法,只好通过 rsync -avz src/ dest/
来同步文件夹。
今天无意中留意到了 GitHub Action 上定义的部署命令:
docker run --rm -v $(pwd):/var/www geshan/php-composer-alpine "composer i --ignore-platform-reqs -vvv"
用 Docker 里面的 composer 来执行安装操作,这不也一起创建软链接吗?在 Docker 创建的软链接是不是意味着在别的 Docker 容器也可以用呢?
想想这个思路没毛病,在本地 PowerShell 环境调用 Docker 里面的 Composer 安装:
docker run --rm -v c:/Users/gq/Code/website/0xffff-env/wwwroot:/var/www geshan/php-composer-alpine "composer i --ignore-platform-reqs -vvv"
竟然可以了!
分析
Windows 下 Docker Desktop 的 Docker 是通过微软自己的 Hyper-V 虚拟机下的 Linux 内核支持运行的。WSL 本身是另一套体系。
于是,带上了 WSL 和 Hyper-V 的 Windows 有点“杂交系统”的味道,涉及到 3 个不同体系的文件系统的互相映射的问题:
在同样操作映射到宿主机下的文件的情况下:
- WSL 里面创建的软链的关系是由 WSL 自己维护的
- Hyper-V 里面 Linux 虚拟机 创建的软链由 Linux 虚拟机 自己维护
- Hyper-V 里面 Linux 虚拟机的 Docker 容器 挂载虚拟机的 Volume 创建的软链接,也是由该 Linux 虚拟机 维护的。也就是说,虽然运行的容器不同,但因为在同一个 Linux 虚拟机,所以这个软链是通用的。
合理猜测,当我们在使用 Windows 版的 Docker Desktop,需要创建 Docker 能用的软链接的时候,是不是可以直接在 PowerShell 这样呢?
docker run --rm -v c:/Users/.../xxx:/xxxxx alpine "ln -s /xxx /yyy"
根据上面分析猜测,我想应该是可以的,有空再验证吧,然后在楼下补充(或者看到这篇帖子的你可以试试(逃
ps: 这里的 wsl 是 1.0 版本