配置: 初始化 ISOS Agent Teams 软件研发模板
CI / lint (push) Successful in 6s

This commit is contained in:
2026-04-19 21:47:08 +08:00
parent 3ab6fe6504
commit 34346be862
202 changed files with 23544 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
# 使用本地缓存资源的 Dockerfile
# 构建前请先运行 ./download-resources.sh 下载所需资源
# 注意:默认情况下 .env 文件对 Dockerfile 是无效的
# ============================================================================
# 基础镜像: 全局环境变量和标签
# ============================================================================
FROM mcr.microsoft.com/devcontainers/base:noble AS base_0_5
ARG CONTAINER_USER_UID=1000
ARG CONTAINER_USER_GID=1000
ARG PROJECT_NAME=isos
ARG DOCKER_GID=984
ENV TZ="Asia/Shanghai" \
CONTAINER_USER_UID="$CONTAINER_USER_UID" \
CONTAINER_USER_GID="$CONTAINER_USER_GID" \
PROJECT_NAME="$PROJECT_NAME" \
DOCKER_GID="$DOCKER_GID" \
PROJECT_ROOT="/workspace" \
DEBIAN_FRONTEND=noninteractive
LABEL maintainer="Arno Jin <arno@arnojin.com>" \
base.image="mcr.microsoft.com/devcontainers/base:noble" \
ubuntu.version="24.04" \
uv.version="installed" \
spec-kit.version="installed" \
container.name="$PROJECT_NAME" \
container.hostname="$PROJECT_NAME"
# ============================================================================
# 阶段 1/4: 系统级安装 + Docker CLI(需要 root 权限)
# ============================================================================
# 注意: mcr.microsoft.com/devcontainers/base:noble 已预装:
# 核心: git, curl, wget, sudo, jq, unzip, zip, gnupg, xz-utils, patch
# 编辑: vim-tiny, vim-common, nano
# 构建: build-essential (gcc, g++, make), libc6-dev, libssl-dev, zlib1g-dev
# 网络: iproute2, net-tools, openssh-client
# 系统: locales, tzdata, ca-certificates, htop, strace, lsof, ncdu, tree, rsync
# Shell: bash, zsh (+ oh-my-zsh)
# 用户: vscode (UID/GID 1000, sudo NOPASSWD, shell=/bin/bash)
# Root: shell=/bin/bash
# 以下工具/库需要额外安装:
FROM base_0_5 AS system_and_docker_1_4
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
set -eu && \
# 配置清华镜像源
sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources \
&& sed -i 's|http://security.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources \
# 移除失效的 Yarn APT 源
&& rm -f /etc/apt/sources.list.d/yarn.list \
/usr/share/keyrings/yarn-archive-keyring.gpg \
/etc/apt/sources.list.d/yarn.list.bak 2>/dev/null || true \
# 安装系统包
&& apt-get update \
&& apt-get install -y --no-install-recommends \
bats tmux ssh ipset iptables \
iputils-ping dnsutils telnet fzf vim xvfb xauth x11-utils \
fonts-inter fonts-noto-cjk fonts-jetbrains-mono fonts-liberation fontconfig fonts-noto-color-emoji \
# Playwright Chromium 核心依赖
libnss3 libnspr4 libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 \
libdrm2 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libxext6 \
libgbm1 libxkbcommon0 libpango-1.0-0 libcairo2 libcairo-gobject2 \
libasound2t64 libcups2t64 libgtk-3-0t64 libvulkan1 xdg-utils \
# Playwright Chromium X11/Wayland 依赖
libdbus-1-3 libx11-6 libxcb1 libxcursor1 libxi6 libxrender1 \
libx11-xcb1 libxcb-shm0 libglib2.0-0t64 \
# Playwright Chromium 渲染/媒体依赖
libfontconfig1 libfreetype6 libgdk-pixbuf-2.0-0 libpangocairo-1.0-0 \
libavcodec60 libopus0 libvpx9 libwebp7 libxslt1.1 libharfbuzz0b \
libjpeg-turbo8 libpng16-16t64 libavif16 liblcms2-2 libevent-2.1-7t64 \
# GPU 支持
libgl1 libegl1 \
# --- Docker CLIDooD 模式,仅 CLI,不含 daemon,使用清华镜像源)---
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
&& chmod a+r /etc/apt/keyrings/docker.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
docker-ce-cli \
docker-buildx-plugin \
docker-compose-plugin \
# --- 系统配置 ---
&& locale-gen zh_CN.UTF-8 \
&& update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 \
&& echo "Asia/Shanghai" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& fc-cache -fv \
&& echo 'fs.inotify.max_user_watches=524288' >> /etc/sysctl.d/10-sysctl.conf \
&& rm -rf /var/lib/apt/lists/* \
/tmp/* \
/var/tmp/* \
/var/cache/apt/archives/*.deb
# ============================================================================
# 阶段 2/4: 安装 Chrome + 配置用户和目录权限(需要 root 权限)
# ============================================================================
FROM system_and_docker_1_4 AS chrome_2_4
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=bind,source=.devcontainer/.cache/chrome,target=/tmp/chrome-cache \
set -eu && \
apt-get update \
&& dpkg -i /tmp/chrome-cache/google-chrome-stable_*.deb || apt-get install -y -f \
&& google-chrome --version \
&& rm -rf /var/lib/apt/lists/* \
&& if [ "$CONTAINER_USER_UID" != "1000" ] || [ "$CONTAINER_USER_GID" != "1000" ]; then \
groupmod -g "$CONTAINER_USER_GID" vscode && \
usermod -u "$CONTAINER_USER_UID" -d "/home/vscode" vscode && \
chown -R "$CONTAINER_USER_UID:$CONTAINER_USER_GID" /home/vscode; \
fi \
&& groupmod -g ${DOCKER_GID} docker 2>/dev/null || groupadd -g ${DOCKER_GID} docker 2>/dev/null || true \
&& usermod -aG docker vscode \
&& mkdir -p $PROJECT_ROOT \
&& chown -R vscode:vscode $PROJECT_ROOT
# ============================================================================
# 阶段 3/4: 安装开发工具(普通用户)
# ============================================================================
FROM chrome_2_4 AS dev_tools_3_4
ENV BIN_PATH="$PROJECT_ROOT/.devcontainer/.volumes/bin" \
NVM_DIR="/home/vscode/.nvm" \
NODE_VERSION="22.22.0" \
UV_PYTHON_DIR="/home/vscode/.local/share/uv" \
UV_BIN="/home/vscode/.local/bin" \
PATH="/home/vscode/.local/bin:$PATH" \
UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
UV_LINK_MODE=copy \
PYTHONUNBUFFERED=1 \
COREPACK_ENABLE_DOWNLOAD_PROMPT=false \
LC_ALL=zh_CN.UTF-8 \
LC_TIME=zh_CN.UTF-8 \
LANG=zh_CN.UTF-8 \
DEVCONTAINER=true \
EDITOR=vim \
VISUAL=vim \
SHELL=/bin/bash \
DISPLAY=""
WORKDIR $PROJECT_ROOT
USER vscode
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
# 使用 --mount=type=bind 挂载缓存资源(避免 COPY 层残留临时文件)
RUN --mount=type=bind,source=.devcontainer/.cache/uv,target=/tmp/uv-cache \
--mount=type=bind,source=.devcontainer/.cache/node,target=/tmp/node-cache \
--mount=type=bind,source=.devcontainer/.cache/npm,target=/tmp/npm-cache \
--mount=type=bind,source=.devcontainer/.cache/vscode,target=/tmp/vscode-cache \
--mount=type=bind,source=.devcontainer/.cache/nvm,target=/tmp/nvm-cache \
--mount=type=bind,source=.devcontainer/.cache/spec-kit,target=/tmp/spec-kit-cache \
--mount=type=bind,source=.devcontainer/.cache/jj,target=/tmp/jj-cache \
mkdir -p "$UV_BIN" "$UV_PYTHON_DIR" "$NVM_DIR" \
&& tar -xzf /tmp/uv-cache/uv-x86_64-unknown-linux-gnu.tar.gz -C "$UV_BIN" --strip-components=1 \
&& tar -xzf /tmp/uv-cache/cpython-*-x86_64-unknown-linux-gnu-install_only.tar.gz -C "$UV_PYTHON_DIR" \
&& ln -sf "$UV_PYTHON_DIR/python/bin/python3.12" "$UV_BIN/python3" \
&& ln -sf "$UV_PYTHON_DIR/python/bin/python3.12" "$UV_BIN/python" \
&& "$UV_BIN/uv" tool install --python "$UV_PYTHON_DIR/python/bin/python3.12" /tmp/spec-kit-cache \
&& ln -sf "/home/vscode/.local/share/uv/tools/specify-cli/bin/specify" "$UV_BIN/specify" \
&& cp -r /tmp/nvm-cache/. "$NVM_DIR/" \
&& [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" \
&& mkdir -p "$NVM_DIR/versions/node" \
&& tar -xJf /tmp/node-cache/node-v*.tar.xz -C "$NVM_DIR/versions/node" \
&& NODE_DIR=$(ls -d "$NVM_DIR/versions/node"/node-v* | head -n1) \
&& mv "$NODE_DIR" "$NVM_DIR/versions/node/v${NODE_VERSION}" \
&& nvm use v${NODE_VERSION} \
&& nvm alias default v${NODE_VERSION} \
&& export PATH="$NVM_DIR/versions/node/v${NODE_VERSION}/bin:$PATH" \
&& export npm_config_registry=https://registry.npmmirror.com \
&& find /tmp/npm-cache/ -maxdepth 1 -name "npm-*.tgz" -exec npm install -g {} + \
&& find /tmp/npm-cache/ -maxdepth 1 -name "*.tgz" ! -name "npm-*.tgz" -exec npm install -g {} + \
# 安装 VSCode 扩展
&& mkdir -p "/home/vscode/.vscode-server/extensions" \
&& for ext in /tmp/vscode-cache/*.vsix; do \
[ -f "$ext" ] || continue; \
ext_name=$(basename "$ext" .vsix); \
temp_dir=$(mktemp -d); \
unzip -q "$ext" -d "$temp_dir" 2>/dev/null || true; \
[ -d "$temp_dir/extension" ] || { rm -rf "$temp_dir"; continue; }; \
version=$(jq -r '.version' "$temp_dir/extension/package.json" 2>/dev/null || echo "0.0.0"); \
ext_dir="/home/vscode/.vscode-server/extensions/${ext_name}-${version}"; \
mkdir -p "$ext_dir"; \
cp -r "$temp_dir/extension"/* "$ext_dir/"; \
rm -rf "$temp_dir"; \
done \
# 安装 Jujutsu (jj) 版本控制工具
&& jj_tar=$(ls /tmp/jj-cache/jj-*.tar.gz 2>/dev/null | head -n1) \
&& if [ -n "$jj_tar" ]; then \
mkdir -p /tmp/jj-extract \
&& tar -xzf "$jj_tar" -C /tmp/jj-extract \
&& cp /tmp/jj-extract/jj "$UV_BIN/jj" \
&& chmod +x "$UV_BIN/jj" \
&& jj --version; \
fi
# 将 Node.js 加入镜像级 PATH,确保非交互式进程也能找到 node/npm
ENV PATH="/home/vscode/.nvm/versions/node/v${NODE_VERSION}/bin:${PATH}"
# ============================================================================
# 阶段 4/4: 配置用户 shell 环境(.bashrc
# ============================================================================
FROM dev_tools_3_4 AS shell_env_4_4
SHELL ["/bin/bash", "-e", "-u", "-o", "pipefail", "-c"]
# 修复 /usr/local/bin/code 包装脚本
USER root
COPY .devcontainer/scripts/code-wrapper /usr/local/bin/code
RUN chmod +x /usr/local/bin/code
# 使用模板文件替代逐行 echo,通过 sed 替换占位符
COPY .devcontainer/templates/bashrc.tail.sh /tmp/bashrc.tail.sh
RUN sed "s|{{NODE_PATH}}|/home/vscode/.nvm/versions/node/v${NODE_VERSION}/bin|g; \
s|{{BIN_PATH}}|${BIN_PATH}|g" \
/tmp/bashrc.tail.sh >> /home/vscode/.bashrc \
&& rm -f /tmp/bashrc.tail.sh \
&& chown vscode:vscode /home/vscode/.bashrc
USER vscode
RUN mkdir -p /home/vscode/.ssh /home/vscode/.claude \
&& chmod 700 /home/vscode/.ssh
CMD ["sleep", "infinity"]