V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
superhot
V2EX  ›  Docker

求教 Dev Container 配置问题,以及同时在 WSL & macOS 上使用 Dev Container 的最佳实践

  •  2
     
  •   superhot · 3 天前 · 346 次点击

    目的

    抹平不同平台的系统差异,统一开发环境为 ubuntu:24.04,让团队内全部成员拥有完全相同的配置与开发体验。

    顺便吐槽一下,macOS 并不像很多人吹得那么好用,虽然是 *nix ,但实际命令行使用体验还是跟 Linux 有区别,为了解决这个问题还要特意下个 homebrew 来装 GNU 套件。相比之下,虽然原生 Windows 上的开发体验很烂,但 WSL 是完完全全的 Linux ,配合 Terminal 和 VS Code ,反而比 macOS 要趁手得多。

    问题

    Dev Container 有两种方式挂载,一种是 bind,一种是 volume

    1. 通过 volume 的方式挂载时,VS Code 不会自动将项目文件拷贝到里面去,需要用 postCreateCommand 执行 Shell 脚本把整个项目仓库代码拉取到命名 volume 中去。这样会带来的问题是,容器内外有两套毫不相干的项目文件,修改互不影响,一般来说,一切修改只能发生在容器内,而本地的项目拷贝只用来做入口,实际上有用的只有 .devcontainer 目录下的内容而已。
    2. 通过 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
    
    5 条回复    2025-01-15 23:49:49 +08:00
    Sinksky
        1
    Sinksky  
       3 天前
    使用 WSL 的情况下,直接在 WSL 里面检出代码文件然后 bind ,没遇到权限问题。
    superhot
        2
    superhot  
    OP
       3 天前
    @Sinksky 容器内的用户和文件权限是什么呢?我的情况是新建了一个用户,没有使用 `ubuntu:24.04` 提供的默认用户
    Sinksky
        3
    Sinksky  
       3 天前
    @superhot 目前容器内外都用的 root ,安装 wsl ubuntu 的时候命令行
    > ubuntu install --root
    Ubuntu 用户默认就是 root
    superhot
        4
    superhot  
    OP
       2 天前
    @Sinksky 这样做确实很方便,但感觉直接使用 root 用户不太好…
    YsHaNg
        5
    YsHaNg  
       2 天前
    docker run 的时候--user $(id -u):$(id -g)似乎没有遇到问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2620 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 05:01 · PVG 13:01 · LAX 21:01 · JFK 00:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.