| FROM ubuntu:22.04 |
|
|
| SHELL ["/bin/bash", "-o", "pipefail", "-c"] |
|
|
| ENV DEBIAN_FRONTEND=noninteractive \ |
| TZ=Asia/Shanghai \ |
| LANG=en_US.UTF-8 \ |
| LC_ALL=en_US.UTF-8 \ |
| PYTHONUNBUFFERED=1 \ |
| PIP_NO_CACHE_DIR=1 \ |
| HOME=/root \ |
| ZSH=/root/.oh-my-zsh \ |
| PORT=7860 |
|
|
| |
| |
| |
| RUN apt-get update && apt-get install -y --no-install-recommends \ |
| ca-certificates \ |
| curl \ |
| wget \ |
| git \ |
| git-lfs \ |
| sudo \ |
| zsh \ |
| locales \ |
| tzdata \ |
| gnupg \ |
| vim \ |
| nano \ |
| jq \ |
| tree \ |
| htop \ |
| tmux \ |
| zip \ |
| unzip \ |
| tar \ |
| xz-utils \ |
| build-essential \ |
| python3 \ |
| python3-pip \ |
| python3-dev \ |
| python-is-python3 \ |
| libasound2 \ |
| libatk-bridge2.0-0 \ |
| libatk1.0-0 \ |
| libc6 \ |
| libcairo2 \ |
| libcups2 \ |
| libdbus-1-3 \ |
| libdrm2 \ |
| libexpat1 \ |
| libgbm1 \ |
| libgcc-s1 \ |
| libglib2.0-0 \ |
| libgtk-3-0 \ |
| libnspr4 \ |
| libnss3 \ |
| libpango-1.0-0 \ |
| libpangocairo-1.0-0 \ |
| libstdc++6 \ |
| libx11-6 \ |
| libx11-xcb1 \ |
| libxcb1 \ |
| libxcomposite1 \ |
| libxcursor1 \ |
| libxdamage1 \ |
| libxext6 \ |
| libxfixes3 \ |
| libxi6 \ |
| libxkbcommon0 \ |
| libxrandr2 \ |
| libxrender1 \ |
| libxshmfence1 \ |
| libxss1 \ |
| libxtst6 \ |
| libatspi2.0-0 \ |
| libwayland-client0 \ |
| libwayland-cursor0 \ |
| libwayland-egl1 \ |
| && locale-gen en_US.UTF-8 \ |
| && update-locale LANG=en_US.UTF-8 \ |
| && rm -rf /var/lib/apt/lists/* |
|
|
| |
| |
| |
| RUN curl -fsSL https://deb.nodesource.com/setup_25.x | bash - \ |
| && apt-get update \ |
| && apt-get install -y --no-install-recommends nodejs \ |
| && npm install -g npm@latest pnpm@latest @anthropic-ai/claude-code \ |
| && npm cache clean --force \ |
| && rm -rf /var/lib/apt/lists/* |
| |
| |
| |
| |
| RUN mkdir -p -m 755 /etc/apt/keyrings \ |
| && curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ |
| | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg \ |
| && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ |
| && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ |
| > /etc/apt/sources.list.d/github-cli.list \ |
| && apt-get update \ |
| && apt-get install -y --no-install-recommends gh \ |
| && rm -rf /var/lib/apt/lists/* |
|
|
| |
| |
| |
| RUN curl -fsSL https://code-server.dev/install.sh | sh \ |
| && python3 -m pip install --no-cache-dir --upgrade pip setuptools wheel \ |
| && python3 -m pip install --no-cache-dir playwright \ |
| && python3 -m playwright install chromium \ |
| && rm -rf /root/.cache/pip |
| |
| |
| |
| |
| RUN git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "${ZSH}" \ |
| && git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "${ZSH}/custom/plugins/zsh-autosuggestions" \ |
| && git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "${ZSH}/custom/plugins/zsh-syntax-highlighting" |
|
|
| RUN mkdir -p "${ZSH}/custom/themes" \ |
| && echo 'PROMPT="%F{green}%n%f:%F{cyan}%~%f > "' > "${ZSH}/custom/themes/minimal.zsh-theme" \ |
| && echo 'RPROMPT="%F{240}[%*]%f"' >> "${ZSH}/custom/themes/minimal.zsh-theme" |
|
|
| RUN cat > /root/.zshrc <<'EOF' |
| export ZSH="$HOME/.oh-my-zsh" |
| zstyle ':omz:update' mode disabled |
| ZSH_THEME="minimal" |
| plugins=(git zsh-autosuggestions zsh-syntax-highlighting) |
| source $ZSH/oh-my-zsh.sh |
| alias ll='ls -alF --color=auto' |
| alias c='clear' |
| alias backup='python3 /root/persistence.py --backup' |
| alias restore='python3 /root/persistence.py --restore' |
| bindkey '^ ' autosuggest-accept |
| EOF |
|
|
| |
| |
| |
| RUN cat > /root/persistence.py <<'EOF' |
| import os, sys, tarfile |
|
|
| BACKUP_NAME = "space_source_backup.tar.gz" |
|
|
| EXCLUDE_DIRS = { |
| "node_modules", ".npm", ".pnpm-store", ".cache", |
| "__pycache__", "venv", ".venv", ".pytest_cache", |
| "CachedExtensionVSIXs", "workspaceStorage", "logs" |
| } |
|
|
| def filter_function(tarinfo): |
| name = os.path.basename(tarinfo.name) |
| if name in EXCLUDE_DIRS: |
| print(f" -> Skipping: {tarinfo.name}") |
| return None |
| return tarinfo |
|
|
| def backup(): |
| print("[*] 正在执行智能备份 (已排除 node_modules/venv 等依赖)...") |
| with tarfile.open(BACKUP_NAME, "w:gz") as tar: |
| for item in os.listdir("/root"): |
| if item != BACKUP_NAME: |
| tar.add(os.path.join("/root", item), arcname=item, filter=filter_function) |
|
|
| size_mb = os.path.getsize(BACKUP_NAME) / (1024 * 1024) |
| print(f"[+] 备份成功!体积:{size_mb:.2f} MB") |
| print(f"[!] 请在侧边栏右键点击 {BACKUP_NAME} 选择 'Download' 下载。") |
| print("[提示] 下次还原后,只需重新执行 npm/pnpm install 或 pip install 即可。") |
|
|
| def restore(): |
| if not os.path.exists(BACKUP_NAME): |
| print(f"[!] 错误:找不到备份文件 {BACKUP_NAME}。请先上传。") |
| return |
| print("[*] 正在还原源代码和配置...") |
| with tarfile.open(BACKUP_NAME, "r:gz") as tar: |
| tar.extractall(path="/root") |
| print("[+] 还原成功!请重新安装项目依赖。") |
|
|
| if __name__ == "__main__": |
| if "--backup" in sys.argv: |
| backup() |
| elif "--restore" in sys.argv: |
| restore() |
| EOF |
|
|
| |
| |
| |
| RUN mkdir -p /root/.config/code-server /root/.local/share/code-server/User |
|
|
| RUN cat > /root/.config/code-server/config.yaml <<'EOF' |
| bind-addr: 0.0.0.0:7860 |
| auth: none |
| EOF |
|
|
| RUN cat > /root/.local/share/code-server/User/settings.json <<'EOF' |
| { |
| "workbench.startupEditor": "none", |
| "telemetry.telemetryLevel": "off", |
| "terminal.integrated.defaultProfile.linux": "zsh", |
| "security.workspace.trust.enabled": false, |
| "workbench.colorTheme": "Default Dark+" |
| } |
| EOF |
|
|
| |
| |
| |
| WORKDIR /root |
| EXPOSE 7860 |
| RUN chsh -s "$(which zsh)" root |
|
|
| ENTRYPOINT ["code-server", "--bind-addr", "0.0.0.0:7860", "--auth", "none", "/root"] |