Dev Container
Configuration
Dev Container 配置步骤如下:
安装 vscode 插件,dev container。
ctrl+shift+p 使用 dev container 命令添加配置文件。
选择 dev container 配置模板(原则上选择基础 debian/ubuntu 即可,其它环境均可通过或许选择 features 进行动态构建)。
Runtime Permission
添加 docker 运行权限,需要添加执行命令,或配置声明。
在 docker-compose 中声明权限:
1 2 3 4 5 6 cap_add: - SYS_PTRACE security_opt: - seccomp:unconfined privileged: true
在 devcontainer.json 中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 "runArgs" : [ "--cap-add=SYS_PTRACE" , "--cap-add=NET_ADMIN" , "--security-opt" , "seccomp=unconfined" , "--gpus=all" , "--privileged" ] ,
上面的配置可以使用 devcontainer 字段配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "capAdd" : [ "SYS_PTRACE" , "NET_ADMIN" ] , "securityOpt" : [ "seccomp=unconfined" ] , "privileged" : true , "runArgs" : [ "--gpus=all" ] , }
GPU Support
配置在 Dev DinD 的开发环境中支持 Nvidia Cuda GPU。
在容器启动前,安装 nvidia-container-toolkit
links:
方案一
使用 devcontainer 提供的官方镜像,需要配置安装 nvidia 源.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 FROM mcr.microsoft.com/devcontainers/base:{VARIANT}RUN <<-EOF distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ tee /etc/apt/sources.list.d/nvidia-container-toolkit.list apt update && apt-get install -y nvidia-container-toolkit && nvidia-ctk runtime configure echo '{"default-runtime":"nvidia"}' $(cat /etc/docker/daemon.json) | jq -s '.[0] + .[1]' | tee /etc/docker/daemon.json rm -rf /var/lib/apt/lists/* /var/cache/* /var/log/* /tmp/* ~/.cache -rf EOF
在 devcontainer.json 中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 "build" : { "dockerfile" : "Dockerfile.gpu" , "args" : { "VARIANT" : "jammy" } } , "capAdd" : [ "SYS_PTRACE" ] , "securityOpt" : [ "seccomp=unconfined" ] , "privileged" : true , "runArgs" : [ "--gpus=all" ] ,
方案二
使用 nvidia 提供的官方 cuda 开发容器为基础,作为 GPU 开发容器配置.
1 2 3 4 5 6 7 8 9 10 FROM nvidia/cuda:12.1 .1 -cudnn8-devel-ubuntu20.04 RUN <<-EOF apt update && apt install -y nvidia-docker2 && nvidia-ctk runtime configure rm rf /var/lib/apt/lists/* /var/cache/* /var/log/* /tmp/* ~/.cache -rf EOF
方案三
方案一,二都需要手动配置源或者使用已经配置好的基础镜像,第三种方法是使用 devcontainer 提供的 cuda feature 来构建.
1 2 3 4 5 6 7 8 9 10 11 "features" : { "ghcr.io/devcontainers/features/common-utils:2" : { "upgradePackages" : false , "username" : "vscode" , "configureZshAsDefaultShell" : true } , "ghcr.io/devcontainers/features/docker-in-docker:2" : { } , "ghcr.io/devcontainers/features/nvidia-cuda:1" : { } } ,
以上方式需要手动安装 docker-container-toolkit
1 2 3 4 5 apt update && apt install -y nvidia-container-toolkit && nvidia-ctk runtime configure ps -ef | grep -E '(dockerd|docker-init.sh)' | head -1 | awk '{print $2}' | xargs sudo kill -9 /usr/local/share/docker-init.sh
QA
sudo apt update error: “Release file is not yet valid”
Features
common features
这里列出了常用 Dev Container 的 features 使用总结。
Common utils
配置容器开发环境用户,方面管理权限。实现参考通过 Dockerfile 创建非 root user 。
devcontainer 有提供专门的 common 帮助用户创建非 root 用户。
1 2 3 4 5 6 7 8 "features" : { "ghcr.io/devcontainers/features/common-utils:2" : { "username" : "vscode" } } , "postCreateCommand" : { "git-completions" : "echo 'source /usr/share/bash-completion/completions/git' >> ~/.bashrc" } ,
Desktop lite
在 devcontainer.json 中配置 desktop-lite
1 2 3 "features" : { "ghcr.io/devcontainers/features/desktop-lite:1" : { } }
导出端口 nVNC 的 vscode 配置 forward port 为 6080 (默认 nVNC 端口)
支持 nVNC 浏览器推荐 Firefox 和 Chrome,这里给出自动集成 Dockerfile 的指令。
1 2 3 4 5 6 apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install -y firefox-esr apt-get update && export DEBIAN_FRONTEND=noninteractive \ && curl -sSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb \ && apt-get -y install /tmp/chrome.deb
DinD
在容器内创建子容器,独立于主机的 docker 实例。在容器中安装 Docker 扩展以及所需的 CLI。
1 2 3 "features" : { "ghcr.io/devcontainers/features/docker-in-docker:2" : { } }
[!TIP]
当容器 daemon 挂掉或者更新 daemon.json
时,可通过 /usr/local/share/docker-init.sh
重启 docker 服务.
features development
devcontainer features 提供了可插拔式得开发工具集成方式。这里简单介绍自定义 features 开发流程。主要参考官方 feature 模板 .
links:
Step 1, feature 开发
clone 官方提供的模板。示例参考
使用官方模板打开 feature 的 devcontainer 开发环境
在 src 下创建 feature, 每个 feature 以子目录构建布局
在 feature 目录下,书写脚本,必须包含有 install.sh 及 devcontainer-feature.json 配置及脚本。详情参考模板
Step 2, feature 测试
在根目录下有 test 目录,某人有全局 _global 测试及各个 feature 测试
在 _global 下可配置测试所有 feature, 具体在 scenarios.json 中注册 feature id, 然后在对应的注册的 id 的脚本 all_tools.sh 中添加 feature 验证命令即可
在 test 目录下可创建单个 feature 的测试脚本,详情参考模板
验证 feature, 使用命令 devcontainer features test -f <feature id> -i <image-name>
在 image-name 的镜像中验证 feature 是否安装成功.
Step 3, feature CI in github action
直接使用模板提供的 CI test.yaml 中配置
在 baseImage 中配置要测试的 image
在 features 中添加要验证的 feature
最后,test 执行成功后,可手动执行 release workflow 发布 feature.
在 Windows/MacOS 上存在性能的 I/O binding 的损失,官方给出了几种解决方案 。
通过 wsl 挂载
通常在 wsl 磁盘挂载效率较高
参考文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 docker run --rm -it -v "$ (pwd):/pwd:delegated" -w /pwd alpine time dd if =/dev/zero of=speedtest bs=1024 count=100000 100000 +0 records in 100000 +0 records outreal 0 m 25.51 s user 0 m 0.11 s sys 0 m 3.19 s docker run --rm -it -v "$ (pwd):/pwd:cached" -w /pwd alpine time dd if =/dev/zero of=speedtest bs=1024 count=100000 100000 +0 records in 100000 +0 records outreal 0 m 28.28 s user 0 m 0.11 s sys 0 m 3.23 s
1 2 3 4 5 6 7 docker run --rm -it -v "$(pwd) :/pwd:delegated" -w /pwd alpine time dd if =/dev/zero of=speedtest bs=1024 count=100000 100000+0 records in 100000+0 records out real 0m 0.22s user 0m 0.02s sys 0m 0.19s
通过测试在 wsl 上挂载不管是 delegated
还是 cached
的效率都是 windows 上得 10x 以上.
Devcontainer in CI
将 devcontainer 构建环境集成在 CI 中,方便开发使用预编译好的镜像,对 CI 流程得 Testing 等能做到同一环境下的统一配置构建方式.
使用 devcontainer/cli 可以轻松的将 devcontainer 集成到 CI 环境中.
links:
1 2 3 4 5 6 7 8 9 10 11 npm install -g @devcontainers/cli git clone https://github.com/microsoft/vscode-remote-try-rust && cd vscode-remote-try-rust devcontainer up --workspace-folder . devcontainer exec --workspace-folder . ls devcontainer build --workspace-folder .
使用 devcontainer 配置构建镜像
1 2 3 4 5 devcontainer build \ --workspace-folder . \ --image-name registry/namespace/image-name:image-tag \ --push true \ --config .devcontainer/build.json
1 2 3 4 5 6 7 { "name" : "xxx-devcontainer" , "build" : { "dockerfile" : "Dockerfile" } }
[!CAUTION]
目前构建镜像,需要配置为 ‘build’ 字段,默认的’image’使用存在 bug .
目前 devcontainer cli 没有 stop 命令,可以通过 docker 查找过滤.
1 2 3 4 5 6 docker stop $(docker ps -q -f ancestor=image-name) docker rm -f $(docker ps -q -f ancestor=image-name) devcontainer up --workspace-folder . --id-label id_name=<identity name> docker ps -q --filter "label=id_name=<identity name>" | xargs docker rm -f
devpod
links: