diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0c110d4..d5777f5 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,106 +1,95 @@ FROM debian:13.1-slim +# 元数据 +LABEL maintainer="i@oo1.dev" \ + description="Development container for Claude and Gemini development" -# 安装中文语言包 -RUN apt-get update && apt-get install -y locales && \ - sed -i 's/^# *zh_CN.UTF-8/zh_CN.UTF-8/' /etc/locale.gen && \ - locale-gen zh_CN.UTF-8 && \ - update-locale LANG=zh_CN.UTF-8 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ - wget \ - curl - -# Install basic development tools and iptables/ipset -RUN apt-get update && apt-get install -y --no-install-recommends \ - less \ - git \ - procps \ - sudo \ - fzf \ - zsh \ - man-db \ - unzip \ - gnupg2 \ - gh \ - iptables \ - ipset \ - iproute2 \ - dnsutils \ - aggregate \ - jq \ - nano \ - vim \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - - -# 创建 usr_vscode 用户和组,UID 和 GID 都是 1000 # https://github.com/nodejs/docker-node/blob/27dd50d60e181b3da84a17d9c5037dcfeb94b781/24/bookworm/Dockerfile#L3 -RUN groupadd --gid 1000 usr_vscode \ - && useradd --uid 1000 --gid usr_vscode --shell /bin/bash --create-home usr_vscode \ - # Show the contents of /etc/passwd - && cat /etc/passwd - -RUN echo "usr_vscode ALL=(root) NOPASSWD: ALL" > /etc/sudoers.d/usr_vscode_user_config && \ - chmod 0440 /etc/sudoers.d/usr_vscode_user_config - - -RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ - && mkdir /commandhistory \ - && touch /commandhistory/.bash_history \ - && chown -R usr_vscode /commandhistory - -# Set `DEVCONTAINER` environment variable to help with orientation -ENV DEVCONTAINER=true - -# Create workspace and config directories and set permissions -RUN mkdir -p /workspace /home/usr_vscode/.claude && \ - chown -R usr_vscode:usr_vscode /workspace /home/usr_vscode/.claude - -WORKDIR /workspace - -# https://github.com/dandavison/delta/releases +# 构建参数 ARG GIT_DELTA_VERSION=0.18.2 +ARG ZSH_IN_DOCKER_VERSION=1.2.1 +ARG PNPM_HOME="/home/usr_vscode/.local/share/pnpm" +ARG PATH="$PNPM_HOME:$PATH" + +# 环境变量 +ENV LANG=zh_CN.UTF-8 \ + LC_ALL=zh_CN.UTF-8 \ + # Set `DEVCONTAINER` environment variable to help with orientation + DEVCONTAINER=true \ + # Set the default shell to zsh rather than sh + SHELL=/bin/zsh \ + # Set the default editor and visual + EDITOR=nano \ + VISUAL=nano \ + POWERLEVEL9K_DISABLE_GITSTATUS=true + +# 安装所有系统依赖 +RUN apt-get update && apt-get install -y --no-install-recommends \ + # 语言包 + locales \ + # 基础工具 + ca-certificates wget curl \ + # 开发工具 + less git procps sudo fzf zsh man-db unzip gnupg2 gh \ + # 网络工具 + iptables ipset iproute2 dnsutils aggregate \ + # 编辑器和实用工具 + jq nano vim \ + # 配置中文环境 + && sed -i 's/^# *zh_CN.UTF-8/zh_CN.UTF-8/' /etc/locale.gen \ + && locale-gen zh_CN.UTF-8 \ + && update-locale LANG=zh_CN.UTF-8 \ + # 清理缓存 + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# 创建用户和配置 sudo +RUN groupadd --gid 1000 usr_vscode \ + && useradd --uid 1000 --gid usr_vscode --shell /bin/zsh --create-home usr_vscode \ + && echo "usr_vscode ALL=(root) NOPASSWD: ALL" > /etc/sudoers.d/usr_vscode_user_config \ + && chmod 0440 /etc/sudoers.d/usr_vscode_user_config \ + && cat /etc/passwd + +# 配置命令历史 +RUN mkdir -p /commandhistory \ + && touch /commandhistory/.bash_history \ + && chown -R usr_vscode:usr_vscode /commandhistory + +# 创建工作目录 +RUN mkdir -p /workspace /home/usr_vscode/.claude \ + && chown -R usr_vscode:usr_vscode /workspace /home/usr_vscode/.claude + +# 安装 git-delta https://github.com/dandavison/delta/releases RUN ARCH=$(dpkg --print-architecture) && \ curl -L -o "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" -# Set up non-root user +WORKDIR /workspace + +# 切换到非 root 用户 USER usr_vscode -# Set the default shell to zsh rather than sh -ENV SHELL=/bin/zsh - -# Set the default editor and visual -ENV EDITOR=nano -ENV VISUAL=nano - -# https://github.com/deluan/zsh-in-docker/releases +# 配置 Zsh https://github.com/deluan/zsh-in-docker/releases # Default powerline10k theme -ENV POWERLEVEL9K_DISABLE_GITSTATUS=true -ARG ZSH_IN_DOCKER_VERSION=1.2.1 -RUN touch /home/usr_vscode/.zshrc -RUN sh -c "$(curl -L -o - https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \ - -p git \ - -p fzf \ - -a "source <(fzf --zsh)" \ - -a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ - -x - # -a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \ - # -a "source /usr/share/doc/fzf/examples/completion.zsh" \ +RUN touch /home/usr_vscode/.zshrc \ + && sh -c "$(curl -L -o - https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \ + -p git \ + -p fzf \ + -a "source <(fzf --zsh)" \ + -a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ + -x + # -a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \ + # -a "source /usr/share/doc/fzf/examples/completion.zsh" \ +# 安装 pnpm 和 Node.js # https://pnpm.io/installation#in-a-docker-container -ARG PNPM_HOME="/home/usr_vscode/.local/share/pnpm" -ARG PATH="$PNPM_HOME:$PATH" - RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.zshrc" SHELL="$(which zsh)" zsh - \ - && pnpm --version \ - && pnpm env use lts --global \ - && pnpm config set store-dir /home/usr_vscode/.pnpm-store + && pnpm --version \ + && pnpm env use lts --global \ + && pnpm config set store-dir /home/usr_vscode/.pnpm-store -# Install Claude +# 安装 AI 工具 RUN pnpm install -g \ - @google/gemini-cli@latest \ - @anthropic-ai/claude-code@latest \ - @musistudio/claude-code-router@latest + @google/gemini-cli@latest \ + @anthropic-ai/claude-code@latest \ + @musistudio/claude-code-router@latest diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 55fa47d..f28680b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -25,19 +25,25 @@ "customizations": { "vscode": { "extensions": [ + // AI "anthropic.claude-code", "google.gemini-cli-vscode-ide-companion", - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "eamodio.gitlens", - "oxc.oxc-vscode", - "editorconfig.editorconfig", - "vitest.explorer", - "vue.volar", "kilocode.kilo-code", "alibaba-cloud.tongyi-lingma", + + // >>>>> + "vue.volar", + "lokalise.i18n-ally", + "eamodio.gitlens", + "vitest.explorer", + // <<<<< + + // 代码质量 / 格式化 / Lint + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", "stylelint.vscode-stylelint", - "lokalise.i18n-ally" + "oxc.oxc-vscode", + "esbenp.prettier-vscode" ], "settings": { "editor.formatOnSave": true, @@ -47,24 +53,25 @@ }, "terminal.integrated.defaultProfile.linux": "zsh", "terminal.integrated.profiles.linux": { - "bash": { - "path": "bash", - "icon": "terminal-bash" - }, - "zsh": { - "path": "zsh", - "icon": "terminal-debian" - } - } + "bash": { "path": "bash", "icon": "terminal-bash" }, + "zsh": { "path": "zsh", "icon": "terminal-debian" } + }, + + // https://stackoverflow.com/questions/75708866/vscode-dev-container-fails-to-load-ms-vscode-js-debug-extension-correctly + // https://davidwesst.com/blog/missing-bootloader-in-vscode-devcontainer/ + /** + * autoAttachFilter 存在问题:会在 NODE_OPTIONS 中注入 bootloader.js 的 --require 参数, + * 并错误地重复拼接 --max-old-space-size,形成类似: + * NODE_OPTIONS= --require /home/.../bootloader.js --max-old-space-size=4096--max-old-space-size=4096 + * 导致启动时报错: + * Error: illegal value for flag --max-old-space-size=4096--max-old-space-size=4096 of type size_t + * 将其设置为 "disabled" 以规避该问题。 + */ + "debug.javascript.autoAttachFilter": "disabled" } } }, - "remoteUser": "usr_vscode", - "mounts": [ - // "source=dev-container-config-${devcontainerId},target=/root/.claude,type=volume", - // "source=node_modules-u_node-${devcontainerId},target=/workspace/node_modules,type=volume", - // "source=dev-container-bashhistory-${devcontainerId},target=/commandhistory,type=volume" - ], + "containerEnv": { // "CLAUDE_CONFIG_DIR": "/home/usr_vscode/.claude", "ANTHROPIC_AUTH_TOKEN": "${localEnv:ANTHROPIC_AUTH_TOKEN}", @@ -73,9 +80,14 @@ "GOOGLE_GEMINI_BASE_URL": "${localEnv:GOOGLE_GEMINI_BASE_URL}", "NODE_OPTIONS": "--max-old-space-size=4096" }, - // "postCreateCommand": "pnpm install", // 容器创建后执行 + "remoteUser": "usr_vscode", + "mounts": [ + // "source=dev-container-bashhistory-${devcontainerId},target=/commandhistory,type=volume" + "source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume" + ], + "postCreateCommand": "sudo chown usr_vscode node_modules", // 容器创建后执行 https://code.visualstudio.com/remote/advancedcontainers/improve-performance "postStartCommand": "pnpm -v", // 每次容器启动时执行 - "postAttachCommand": "pnpm config get store-dir", // 连接到容器后执行 + // "postAttachCommand": "pnpm config get store-dir", // 连接到容器后执行 // "updateRemoteUserUID": true, // "waitFor": "postStartCommand" "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",