目的
抹平不同平台的系统差异,统一开发环境为 ubuntu:24.04 ,让团队内全部成员拥有完全相同的配置与开发体验。
顺便吐槽一下,macOS 并不像很多人吹得那么好用,虽然是 *nix ,但实际命令行使用体验还是跟 Linux 有区别,为了解决这个问题还要特意下个 homebrew 来装 GNU 套件。相比之下,虽然原生 Windows 上的开发体验很烂,但 WSL 是完完全全的 Linux ,配合 Terminal 和 VS Code ,反而比 macOS 要趁手得多。
问题
Dev Container 有两种方式挂载,一种是 bind ,一种是 volume 。
- 通过
volume 的方式挂载时,VS Code 不会自动将项目文件拷贝到里面去,需要用 postCreateCommand 执行 Shell 脚本把整个项目仓库代码拉取到命名 volume 中去。这样会带来的问题是,容器内外有两套毫不相干的项目文件,修改互不影响,一般来说,一切修改只能发生在容器内,而本地的项目拷贝只用来做入口,实际上有用的只有 .devcontainer 目录下的内容而已。
- 通过
bind 的方式挂载时,VS Code 将本地文件映射到容器中去,容器内外共享文件,修改也是同步且双向可见的。然而这个方法在 WSL 下会有文件权限问题。
macOS 下,容器内的文件继承了容器内 dev 用户与组的权限,项目根目录下的 .git 也可正常使用。
而在 WSL 下,文件未能正确继承容器用户 dev 的权限,而是 ubuntu 的,这就需要额外在 postCreateCommand 执行 Shell 脚本,通过 sudo chown -R "$USERNAME":"$USERNAME" ~ 修改用户目录下所有文件权限为 dev:dev 。这能解决 WSL 的问题,但又带来了新的问题,同样的命令在 macOS 下会报错:
chown: changing ownership of '/home/dev/project/.git/objects/0d/6fb98ba513f068f7a1839e4e92c0fe482f256a': Permission denied
尝试过判断宿主机操作系统类型,并通过 ${localEnv:HOST_OS_TYPE} 传递给 postCreateCommand 的脚本。但没法仅通过 VS Code 与 devcontainer.json 实现,必须事先手动在命令行中添加此环境变量 export HOST_OS_TYPE="$(uname)" 。
个人是比较偏向 bind 挂载的,感觉 volume 虽然干净,但还要额外拉取代码,同时存在两份,不太优雅。
然而上面的问题不知如何解决,AI 问过无果,所以想来问问是否有更好的做法。
当前配置
devcontainer.json :
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"USERNAME": "dev"
}
},
"workspaceFolder": "/home/dev/project",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/dev/project,type=bind,consistency=cached",
"remoteUser": "dev",
"containerUser": "dev",
"containerEnv": {
"USERNAME": "dev"
},
Dockerfile :
FROM ubuntu:24.04
ARG USERNAME
RUN groupadd ${USERNAME} \
&& useradd -m -s /bin/bash -g ${USERNAME} ${USERNAME} \
&& usermod -aG sudo ${USERNAME} \
&& mkdir -p /etc/sudoers.d \
&& echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd \
&& chmod 0440 /etc/sudoers.d/nopasswd
|