From 39820e656a9822e3b31df93d0abc33c02b2e56d1 Mon Sep 17 00:00:00 2001 From: csh Date: Tue, 9 Dec 2025 16:06:25 +0800 Subject: [PATCH] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=92=8C`docker-runner`=E9=A1=B9=E7=9B=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :sparkles: 支持`docker`部署`archlinux`,预装`clang`跨平台编译工具链 --- .gitea/workflows/immortal_wrt.yml | 33 - .gitea/workflows/ubuntu_system_info.yml | 99 + DEPLOYMENT.md | 1753 +++-------------- docker-runner/buildx/register.sh | 321 --- .../{buildx => common}/check_crlf.sh | 0 .../{buildx => common}/entrypoint.sh | 195 +- docker-runner/{buildx => common}/manage.sh | 0 .../{standard => common}/register.sh | 5 +- docker-runner/{buildx => common}/setup.sh | 0 .../presets/buildx-archlinux/Dockerfile | 68 + .../buildx-archlinux/docker-compose.yml | 35 + .../buildx-ubuntu-22}/Dockerfile | 0 .../buildx-ubuntu-22}/docker-compose.yml | 18 +- .../standard-ubuntu-22}/Dockerfile | 0 .../standard-ubuntu-22}/docker-compose.yml | 15 +- docker-runner/standard/entrypoint.sh | 134 -- docker-runner/standard/manage.sh | 288 --- docker-runner/standard/setup.sh | 141 -- 18 files changed, 639 insertions(+), 2466 deletions(-) delete mode 100644 .gitea/workflows/immortal_wrt.yml create mode 100644 .gitea/workflows/ubuntu_system_info.yml delete mode 100644 docker-runner/buildx/register.sh rename docker-runner/{buildx => common}/check_crlf.sh (100%) rename docker-runner/{buildx => common}/entrypoint.sh (53%) rename docker-runner/{buildx => common}/manage.sh (100%) rename docker-runner/{standard => common}/register.sh (97%) rename docker-runner/{buildx => common}/setup.sh (100%) create mode 100644 docker-runner/presets/buildx-archlinux/Dockerfile create mode 100644 docker-runner/presets/buildx-archlinux/docker-compose.yml rename docker-runner/{buildx => presets/buildx-ubuntu-22}/Dockerfile (100%) rename docker-runner/{buildx => presets/buildx-ubuntu-22}/docker-compose.yml (57%) rename docker-runner/{standard => presets/standard-ubuntu-22}/Dockerfile (100%) rename docker-runner/{standard => presets/standard-ubuntu-22}/docker-compose.yml (63%) delete mode 100644 docker-runner/standard/entrypoint.sh delete mode 100644 docker-runner/standard/manage.sh delete mode 100644 docker-runner/standard/setup.sh diff --git a/.gitea/workflows/immortal_wrt.yml b/.gitea/workflows/immortal_wrt.yml deleted file mode 100644 index 21e5f36..0000000 --- a/.gitea/workflows/immortal_wrt.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Hello from ImmortalWrt - -on: - push: - branches: - - main - -jobs: - say-hello: - runs-on: company - - steps: - - name: 打印问候 - run: echo "Hello form ImmortalWrt Router!" - - - name: 显示系统信息 - run: | - echo "===== 系统信息 =====" - uname -a - cat /etc/openwrt_release || echo "不是 OpenWrt 环境" - - - name: 显示 CPU 和内存 - run: | - echo "===== CPU 信息 =====" - cat /proc/cpuinfo | grep "model name" | head -1 || echo "ARM 架构" - echo "===== 内存信息 =====" - free -h - - - name: 显示磁盘空间 - run: df -h - - - name: 列出当前目录 - run: ls -la diff --git a/.gitea/workflows/ubuntu_system_info.yml b/.gitea/workflows/ubuntu_system_info.yml new file mode 100644 index 0000000..f29ea41 --- /dev/null +++ b/.gitea/workflows/ubuntu_system_info.yml @@ -0,0 +1,99 @@ +name: Ubuntu System Information + +on: + push: + branches: + - main + workflow_dispatch: # 允许手动触发 + +jobs: + show-system-info: + runs-on: ubuntu-22.04 + + steps: + - name: 打印问候 + run: | + echo "=====================================" + echo " Ubuntu System Information Check " + echo "=====================================" + echo "" + + - name: 显示系统信息 + run: | + echo "===== 系统版本 =====" + cat /etc/os-release + echo "" + echo "===== 内核信息 =====" + uname -a + echo "" + echo "===== LSB 信息 =====" + lsb_release -a + + - name: 显示 CPU 信息 + run: | + echo "===== CPU 详细信息 =====" + lscpu + echo "" + echo "===== CPU 型号 =====" + cat /proc/cpuinfo | grep "model name" | head -1 + echo "" + echo "===== CPU 核心数 =====" + nproc + + - name: 显示内存信息 + run: | + echo "===== 内存使用情况 =====" + free -h + echo "" + echo "===== 内存详细信息 =====" + cat /proc/meminfo | grep -E 'MemTotal|MemFree|MemAvailable' + + - name: 显示磁盘信息 + run: | + echo "===== 磁盘使用情况 =====" + df -h + echo "" + echo "===== 磁盘分区信息 =====" + lsblk + + - name: 显示网络信息 + run: | + echo "===== 网络接口 =====" + ip addr show + echo "" + echo "===== 路由表 =====" + ip route show + echo "" + echo "===== DNS 配置 =====" + cat /etc/resolv.conf + + - name: 显示已安装的软件 + run: | + echo "===== Python 版本 =====" + python3 --version + echo "" + echo "===== Node.js 版本 =====" + node --version || echo "Node.js 未安装" + echo "" + echo "===== Docker 版本 =====" + docker --version || echo "Docker 未安装" + echo "" + echo "===== Git 版本 =====" + git --version + + - name: 显示环境变量 + run: | + echo "===== 重要环境变量 =====" + echo "PATH: $PATH" + echo "HOME: $HOME" + echo "USER: $USER" + echo "SHELL: $SHELL" + echo "PWD: $PWD" + + - name: 显示当前目录 + run: | + echo "===== 当前工作目录 =====" + pwd + echo "" + echo "===== 目录内容 =====" + ls -lah diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 0a0c51e..d77de1a 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,11 +1,13 @@ -# 🚀 Gitea Runner Docker 部署完整教程 +# 🚀 Gitea Runner Docker 部署教程 ## 📋 目录 - [简介](#-简介) +- [目录结构](#-目录结构) - [版本选择](#-版本选择) -- [版本 1:标准版](#-版本-1标准版推荐) -- [版本 2:Buildx 多架构版](#-版本-2buildx-多架构版) +- [部署步骤](#-部署步骤) +- [管理命令](#-管理命令) +- [Buildx 多架构构建示例](#-buildx-多架构构建示例) - [版本对比](#️-版本对比) - [常见问题](#-常见问题) @@ -13,1069 +15,122 @@ ## 💡 简介 -Gitea Runner 是 Gitea 的 CI/CD 执行器,类似于 GitLab Runner 或 GitHub Actions Runner,用于执行 Gitea Actions 工作流。 +Gitea Runner 是 Gitea 的 CI/CD 执行器,类似于 GitLab Runner 或 GitHub Actions Runner,用于执行 Gitea Actions 工作流。 + +本项目提供了标准版和 Buildx 版两种部署方案,通过预设配置快速部署。 + +--- + +## 📂 目录结构 + +```txt +docker-runner/ +├── common/ # 通用脚本(所有版本共用) +│ ├── check_crlf.sh # Windows 换行符检查工具 +│ ├── entrypoint.sh # 容器启动脚本 +│ ├── setup.sh # Runner 安装脚本 +│ ├── register.sh # Runner 注册脚本 +│ └── manage.sh # Runner 管理脚本 +│ +└── presets/ # 预设配置(选择一个使用) + ├── standard-ubuntu-22/ # 标准版 (Ubuntu 22.04) + │ ├── Dockerfile + │ └── docker-compose.yml + ├── buildx-ubuntu-22/ # Buildx 版 (Ubuntu 22.04) + │ ├── Dockerfile + │ └── docker-compose.yml + └── buildx-archlinux/ # Buildx 版 (Arch Linux) + ├── Dockerfile + └── docker-compose.yml +``` + +**说明:** + +- `common/` 目录中的脚本由所有版本共享,通过 docker-compose.yml 挂载到容器 +- `presets/` 目录中每个子目录是一个完整的预设配置,包含 Dockerfile 和 docker-compose.yml +- 数据持久化在 `runner-data/` 目录(自动创建),包含 runner 配置、缓存和 act_runner 二进制文件 --- ## 🎯 版本选择 -### 📦 版本 1:标准版(推荐) +### 📦 标准版(推荐) -**适合场景:** +**适合场景:** - ✅ 大多数日常使用场景 -- ✅ 只需在 arm64 架构上运行应用 +- ✅ 只需在当前架构上运行应用 - ✅ 简单的 CI/CD 流程 - ✅ 不需要构建多架构容器镜像 -**特点:** +**特点:** -- 🪶 轻量级,镜像体积约 400MB -- ⚡ 配置简单,启动快速(5-10 秒) -- 🔒 无需特权模式,更安全 +- 🪶 轻量级,镜像体积约 400MB +- ⚡ 配置简单,启动快速(5-10 秒) +- 🔒 无需特权模式,更安全 - 🎯 易于维护 -### 🚀 版本 2:Buildx 多架构版 +**预设:** `presets/standard-ubuntu-22/` -**适合场景:** +--- + +### 🚀 Buildx 多架构版 + +**适合场景:** - ✅ 需要构建 arm64 + amd64 双架构镜像 - ✅ 发布容器镜像到公共仓库 - ✅ 跨平台应用开发和测试 - ✅ 高级 CI/CD 需求 -**特点:** +**特点:** - 🌐 支持 Docker Buildx 多架构构建 - 🔧 内置 QEMU 跨架构模拟 - 🤖 自动配置 Buildx builder - ⚠️ 需要特权模式和 Docker socket +**预设选择:** + +- `presets/buildx-ubuntu-22/` - Ubuntu 22.04 基础(推荐) +- `presets/buildx-archlinux/` - Arch Linux 滚动更新版本 + --- -## 📦 版本 1:标准版(推荐) +## 🚀 部署步骤 -### 📂 目录结构 +### 标准版部署 -```txt -gitea-runner/ -├── Dockerfile # 容器构建文件 -├── docker-compose.yml # Docker Compose 配置 -├── entrypoint.sh # 容器启动脚本 -├── setup.sh # Runner 安装脚本 -├── register.sh # Runner 注册脚本 -├── manage.sh # Runner 管理脚本 -└── runner-data/ # 数据持久化目录(自动创建) - └── runners/ # 多个 runner 存储目录 - ├── runner-1/ - │ ├── .runner - │ ├── config.yaml - │ └── cache/ - └── ... -``` - -### 📝 文件配置 - -#### 1️⃣ Dockerfile - -创建 `Dockerfile` 文件: - -```dockerfile -FROM ubuntu:22.04 - -# 设置环境变量避免交互式安装 -ENV DEBIAN_FRONTEND=noninteractive - -# 更新系统并安装必要软件 -RUN apt-get update && apt-get install -y \ - curl \ - git \ - python3 \ - python3-yaml \ - supervisor \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -# 创建必要目录 -RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor - -# 设置工作目录 -WORKDIR /data - -# 使用自定义入口点 -ENTRYPOINT ["/data/entrypoint.sh"] -``` - -#### 2️⃣ docker-compose.yml - -创建 `docker-compose.yml` 文件: - -```yaml -services: - gitea-runner: - build: . - container_name: gitea-runner - restart: unless-stopped - volumes: - - ./runner-data:/data - - ./setup.sh:/data/setup.sh:ro - - ./register.sh:/data/register.sh:ro - - ./manage.sh:/data/manage.sh:ro - - ./entrypoint.sh:/data/entrypoint.sh:ro - - # 如果需要在容器内运行 Docker,取消下面的注释 - # - /var/run/docker.sock:/var/run/docker.sock - - environment: - - TZ=Asia/Shanghai - - # 如果需要使用代理,取消下面的注释并修改端口 - # 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP - # - http_proxy=http://host.docker.internal:20122 - # - https_proxy=http://host.docker.internal:20122 - # - HTTP_PROXY=http://host.docker.internal:20122 - # - HTTPS_PROXY=http://host.docker.internal:20122 - # - no_proxy=localhost,127.0.0.1 - - # Linux 系统需要取消下面的注释以支持 host.docker.internal - # extra_hosts: - # - "host.docker.internal:host-gateway" -``` - -#### 3️⃣ entrypoint.sh - -创建 `entrypoint.sh` 文件: +#### 1. 进入预设目录 ```bash -#!/bin/bash -set -e - -echo "===================================" -echo "Gitea Runner Container Starting..." -echo "===================================" - -# 定义路径 -PERSISTENT_BIN="/data/bin" -RUNNER_PATH="$PERSISTENT_BIN/act_runner" -SYSTEM_LINK="/usr/local/bin/act_runner" - -# 创建必要目录 -mkdir -p /data/runners -mkdir -p "$PERSISTENT_BIN" -mkdir -p /var/log/supervisor -mkdir -p /var/run - -# 创建主 supervisor 配置文件 -cat > /etc/supervisor/supervisord.conf < $RUNNER_PATH" - fi - - # 验证版本 - RUNNER_VERSION=$("$SYSTEM_LINK" --version 2>/dev/null || echo "unknown") - echo " Version: $RUNNER_VERSION" -elif [ -f "$SYSTEM_LINK" ]; then - # 旧版本可能在系统路径,迁移到持久化目录 - echo "⚠ Found act_runner in system path, migrating to persistent storage..." - cp "$SYSTEM_LINK" "$RUNNER_PATH" - chmod +x "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo " ✓ Migrated to: $RUNNER_PATH" -else - # 没有找到 act_runner - echo "⚠ act_runner not installed yet!" - echo "" - echo "Please run the setup script first:" - echo " docker-compose exec gitea-runner /data/setup.sh" - echo "" - echo "Container is waiting..." - - # 等待 act_runner 安装 - while [ ! -f "$RUNNER_PATH" ] && [ ! -f "$SYSTEM_LINK" ]; do - sleep 10 - done - - # 再次检查并创建链接 - if [ -f "$RUNNER_PATH" ]; then - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and linked!" - elif [ -f "$SYSTEM_LINK" ]; then - cp "$SYSTEM_LINK" "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and migrated!" - fi -fi - -# 为每个已注册的 runner 创建 supervisor 配置 -echo "" -echo "Scanning for registered runners..." -RUNNER_COUNT=0 - -if [ -d "/data/runners" ]; then - for runner_dir in /data/runners/*/; do - if [ -d "$runner_dir" ]; then - runner_name=$(basename "$runner_dir") - - if [ -f "$runner_dir/.runner" ] && [ -f "$runner_dir/config.yaml" ]; then - echo "Found runner: $runner_name" - - # 创建该 runner 的 supervisor 配置 - cat > "/etc/supervisor/conf.d/runner-${runner_name}.conf" </dev/null | grep -oP 'version \K[0-9.]+' || echo "unknown") - echo "⚠ act_runner already installed (version: $CURRENT_VERSION)" - echo " Location: $INSTALL_PATH" - echo "" - read -p "Do you want to reinstall/upgrade? (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Installation cancelled." - exit 0 - fi - rm -f "$INSTALL_PATH" "$SYSTEM_PATH" -fi - -# 获取要安装的版本 -echo "Available versions: https://dl.gitea.com/act_runner/" -echo "" -read -p "Enter version to install (default: 0.2.13): " RUNNER_VERSION -RUNNER_VERSION=${RUNNER_VERSION:-0.2.13} - -ARCH=$(uname -m) -case "$ARCH" in - x86_64) - RUNNER_ARCH="amd64" - ;; - aarch64|arm64) - RUNNER_ARCH="arm64" - ;; - armv7l) - RUNNER_ARCH="arm-7" - ;; - *) - echo "⚠ Unknown architecture: $ARCH" - RUNNER_ARCH="arm64" - ;; -esac - -# 确认架构 -echo "" -echo "Detected architecture: $ARCH -> $RUNNER_ARCH" -read -p "Is this correct? (Y/n): " -n 1 -r -echo -if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "" - echo "Available architectures:" - echo " 1. amd64 (x86_64)" - echo " 2. arm64 (aarch64)" - echo " 3. arm-7 (armv7l)" - read -p "Select architecture (1-3): " ARCH_CHOICE - case "$ARCH_CHOICE" in - 1) RUNNER_ARCH="amd64" ;; - 2) RUNNER_ARCH="arm64" ;; - 3) RUNNER_ARCH="arm-7" ;; - *) - echo "Invalid choice. Exiting." - exit 1 - ;; - esac -fi - -DOWNLOAD_URL="https://dl.gitea.com/act_runner/${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-${RUNNER_ARCH}" - -echo "" -echo "Download Configuration:" -echo " Version: $RUNNER_VERSION" -echo " Architecture: $RUNNER_ARCH" -echo " URL: $DOWNLOAD_URL" -echo " Install Location: $INSTALL_PATH (persistent)" -echo "" -read -p "Proceed with download? (Y/n): " -n 1 -r -echo -if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "Installation cancelled." - exit 0 -fi - -echo "" -echo "Downloading act_runner..." -echo "" - -# 下载到持久化目录 -if curl -L "$DOWNLOAD_URL" -o "$INSTALL_PATH"; then - chmod +x "$INSTALL_PATH" - - # 同时创建软链接到系统路径 - ln -sf "$INSTALL_PATH" "$SYSTEM_PATH" - - # 验证安装 - if $INSTALL_PATH --version; then - echo "" - echo "==========================================" - echo "✓ act_runner installed successfully!" - echo "==========================================" - echo "" - echo "Version: $($INSTALL_PATH --version)" - echo "Location: $INSTALL_PATH (persistent storage)" - echo "" - echo "Next steps:" - echo "1. Register the runner:" - echo " docker-compose exec gitea-runner /data/register.sh" - echo "" - echo "2. Restart the container:" - echo " docker-compose restart" - echo "" - echo "Note: act_runner is saved in persistent storage" - echo " and will survive container restarts." - echo "" - else - echo "" - echo "✗ Installation verification failed!" - rm -f "$INSTALL_PATH" "$SYSTEM_PATH" - exit 1 - fi -else - echo "" - echo "✗ Download failed!" - echo "Please check:" - echo " - Internet connection" - echo " - Version number is correct: $RUNNER_VERSION" - echo " - Architecture is correct: $RUNNER_ARCH" - echo " - URL is accessible: $DOWNLOAD_URL" - echo "" - echo "You can check available versions at:" - echo " https://dl.gitea.com/act_runner/" - exit 1 -fi +../../common/check_crlf.sh ``` -#### 5️⃣ register.sh - -创建 `register.sh` 文件: - -```bash -#!/bin/bash -set -e - -echo "==========================================" -echo " Gitea Runner Registration Script " -echo "==========================================" -echo "" - -# 检查 act_runner 是否安装 -if ! command -v act_runner &> /dev/null; then - echo "✗ act_runner is not installed!" - echo "" - echo "Please run the setup script first:" - echo " docker-compose exec gitea-runner /data/setup.sh" - exit 1 -fi - -echo "✓ act_runner found: $(act_runner --version)" -echo "" - -# 获取注册信息并验证 -while true; do - read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE - - # 验证 URL 格式 - if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then - echo "✗ Error: URL must start with http:// or https://" - echo "" - continue - fi - - # 移除末尾的斜杠 - GITEA_INSTANCE="${GITEA_INSTANCE%/}" - echo "✓ URL validated: $GITEA_INSTANCE" - break -done - -read -p "Enter registration token: " GITEA_TOKEN - -if [ -z "$GITEA_TOKEN" ]; then - echo "✗ Error: Token cannot be empty!" - exit 1 -fi - -read -p "Enter runner name (default: docker-runner): " RUNNER_NAME -RUNNER_NAME=${RUNNER_NAME:-docker-runner} - -# 多个 label(逗号分隔,无空格) -# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18 -read -p "Enter runner labels (default: ubuntu-22.04:docker://ubuntu:22.04): " RUNNER_LABELS -RUNNER_LABELS=${RUNNER_LABELS:-ubuntu-22.04:host://ubuntu:22.04} - -# 创建 runner 目录 -RUNNER_DIR="/data/runners/${RUNNER_NAME}" -mkdir -p "$RUNNER_DIR" -cd "$RUNNER_DIR" - -echo "" -echo "Registration Information:" -echo " Instance: $GITEA_INSTANCE" -echo " Name: $RUNNER_NAME" -echo " Labels: $RUNNER_LABELS" -echo " Directory: $RUNNER_DIR" -echo "" - -# 检查是否已经注册 -if [ -f ".runner" ] || [ -f "config.yaml" ]; then - echo "⚠ Runner already exists in this directory!" - read -p "Do you want to re-register? This will overwrite existing configuration. (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Registration cancelled." - exit 0 - fi - - echo "Cleaning up existing runner..." - - # 停止现有 runner - echo "Stopping existing runner..." - supervisorctl stop "runner-${RUNNER_NAME}" 2>/dev/null || true - - # 删除 supervisor 配置 - rm -f "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" - - # 重新加载 supervisor - supervisorctl reread 2>/dev/null || true - supervisorctl update 2>/dev/null || true - - # 删除日志 - rm -f "/var/log/supervisor/runner-${RUNNER_NAME}".*.log* - - # 删除旧配置和缓存 - rm -f .runner config.yaml - rm -rf cache -fi - -# 执行注册 -echo "" -echo "Registering runner..." -act_runner register \ - --instance "$GITEA_INSTANCE" \ - --token "$GITEA_TOKEN" \ - --name "$RUNNER_NAME" \ - --labels "$RUNNER_LABELS" \ - --no-interactive - -if [ ! -f ".runner" ]; then - echo "" - echo "✗ Registration failed! .runner file not created." - exit 1 -fi - -echo "✓ Registration successful!" - -# 生成配置文件 -echo "" -echo "Generating config.yaml..." -act_runner generate-config > config.yaml - -echo "✓ Configuration file generated!" - -# 创建缓存目录 -mkdir -p cache - -# 使用 Python 修改配置(最可靠的方法) -echo "" -echo "Configuring runner settings..." - -if command -v python3 &> /dev/null; then - python3 << PYEOF -import yaml -import sys - -try: - # 读取生成的配置 - with open('config.yaml', 'r') as f: - config = yaml.safe_load(f) - - # 读取 .runner 获取实际注册的 labels - import json - with open('.runner', 'r') as f: - runner_data = json.load(f) - - # 使用 .runner 中的 labels(这是实际注册的) - registered_labels = runner_data.get('labels', []) - - # 修改配置 - if 'runner' not in config: - config['runner'] = {} - - # 使用实际注册的 labels - config['runner']['labels'] = registered_labels - config['runner']['capacity'] = 2 - - # 启用缓存 - if 'cache' not in config: - config['cache'] = {} - config['cache']['enabled'] = True - config['cache']['dir'] = './cache' - - # 保存配置 - with open('config.yaml', 'w') as f: - yaml.dump(config, f, default_flow_style=False, sort_keys=False) - - print("✓ Configuration updated using Python") - print(f" - Labels: {registered_labels}") - print(f" - Capacity: 2") - print(f" - Cache enabled: ./cache") - sys.exit(0) - -except Exception as e: - print(f"✗ Python configuration failed: {e}", file=sys.stderr) - sys.exit(1) -PYEOF - - PYTHON_EXIT=$? - - if [ $PYTHON_EXIT -ne 0 ]; then - echo "" - echo "⚠ Python configuration failed, using basic sed..." - - # 基本的 sed 修改(只修改简单的值,不动 labels) - sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true - sed -i 's/enabled: false/enabled: true/g' config.yaml || true - sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true - - echo "✓ Basic configuration applied" - echo " Note: Please manually verify labels in config.yaml match .runner" - fi -else - echo "⚠ Python3 not found, applying basic configuration..." - - # 基本的 sed 修改 - sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true - sed -i 's/enabled: false/enabled: true/g' config.yaml || true - sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true - - echo "✓ Basic configuration applied" - echo " Note: Labels will use act_runner defaults" -fi - -# 验证配置文件 -echo "" -echo "Validating configuration..." - -# 检查 YAML 语法 -if command -v python3 &> /dev/null; then - python3 << PYEOF -import yaml -import sys -try: - with open('config.yaml', 'r') as f: - yaml.safe_load(f) - print("✓ config.yaml syntax is valid") - sys.exit(0) -except Exception as e: - print(f"✗ config.yaml syntax error: {e}", file=sys.stderr) - sys.exit(1) -PYEOF - - if [ $? -ne 0 ]; then - echo "" - echo "✗ Configuration file has syntax errors!" - echo " Backup available at: config.yaml.bak" - exit 1 - fi -fi - -# 显示配置摘要 -echo "" -echo "Configuration Summary:" -echo "-------------------------------------------" -echo ".runner labels:" -cat .runner | grep -A 10 '"labels"' | head -15 -echo "" -echo "config.yaml labels:" -grep -A 5 "^ labels:" config.yaml | head -10 - -# 创建 supervisor 配置 -echo "" -echo "Creating supervisor configuration..." -cat > "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" </dev/null || \ - supervisorctl start "runner-${RUNNER_NAME}" - -# 等待启动 -sleep 3 - -# 显示状态 -RUNNER_STATUS=$(supervisorctl status "runner-${RUNNER_NAME}" 2>/dev/null || echo "UNKNOWN") - -echo "" -echo "==========================================" -echo "✓ Runner registered and started!" -echo "==========================================" -echo "" -echo "Runner Information:" -echo " Name: $RUNNER_NAME" -echo " Directory: $RUNNER_DIR" -echo " Status: $RUNNER_STATUS" -echo "" -echo "Configuration files:" -echo " .runner: $(ls -lh .runner 2>/dev/null | awk '{print $5}' || echo 'N/A')" -echo " config.yaml: $(ls -lh config.yaml 2>/dev/null | awk '{print $5}' || echo 'N/A')" -echo "" -echo "Useful commands:" -echo " View logs: docker-compose exec gitea-runner /data/manage.sh logs ${RUNNER_NAME}" -echo " Follow logs: docker-compose exec gitea-runner /data/manage.sh follow ${RUNNER_NAME}" -echo " Check status: docker-compose exec gitea-runner /data/manage.sh status" -echo " Restart: docker-compose exec gitea-runner /data/manage.sh restart ${RUNNER_NAME}" -echo "" - -# 显示最近的日志 -if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" ]; then - echo "Recent logs:" - echo "-------------------------------------------" - tail -n 20 "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" 2>/dev/null || echo "No logs yet" - echo "" -fi - -# 检查是否有错误 -if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" ]; then - # 只查找 error/fatal/panic 级别的日志 - ERR_CONTENT=$(grep -E 'level=(error|fatal|panic)' \ - "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" | tail -n 5 2>/dev/null) - - if [ -n "$ERR_CONTENT" ]; then - echo "❌ Recent errors detected:" - echo "-------------------------------------------" - echo "$ERR_CONTENT" - echo "" - echo "Check full error log with:" - echo " docker-compose exec gitea-runner cat /var/log/supervisor/runner-${RUNNER_NAME}.err.log" - fi -fi -``` - -#### 6️⃣ manage.sh - -创建 `manage.sh` 文件: - -```bash -#!/bin/bash - -echo "==========================================" -echo " Gitea Runner Management Tool " -echo "==========================================" -echo "" - -# 函数:列出所有 runners -list_runners() { - echo "Registered Runners:" - echo "-------------------------------------------" - - if [ ! -d "/data/runners" ] || [ -z "$(ls -A /data/runners 2>/dev/null)" ]; then - echo "No runners registered yet." - return - fi - - printf "%-20s %-15s %-30s\n" "Name" "Status" "Log File" - echo "-------------------------------------------" - - for runner_dir in /data/runners/*/; do - if [ -d "$runner_dir" ]; then - runner_name=$(basename "$runner_dir") - - if [ -f "$runner_dir/.runner" ]; then - # 获取状态 - status=$(supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}') - [ -z "$status" ] && status="NOT_LOADED" - - log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - printf "%-20s %-15s %-30s\n" "$runner_name" "$status" "$log_file" - fi - fi - done - echo "" -} - -# 函数:查看 runner 详细信息 -show_runner() { - local runner_name=$1 - local runner_dir="/data/runners/${runner_name}" - - if [ ! -d "$runner_dir" ]; then - echo "✗ Runner '$runner_name' not found!" - return 1 - fi - - echo "Runner Details: $runner_name" - echo "-------------------------------------------" - echo "Directory: $runner_dir" - - if [ -f "$runner_dir/config.yaml" ]; then - echo "" - echo "Configuration:" - cat "$runner_dir/config.yaml" - fi - - echo "" - echo "Status:" - supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}' - echo "" -} - -# 函数:删除 runner -delete_runner() { - local runner_name=$1 - local runner_dir="/data/runners/${runner_name}" - - if [ ! -d "$runner_dir" ]; then - echo "✗ Runner '$runner_name' not found!" - return 1 - fi - - echo "⚠ Warning: This will permanently delete runner '$runner_name'" - read -p "Are you sure? (y/N): " -n 1 -r - echo - - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Deletion cancelled." - return 0 - fi - - echo "Stopping runner..." - supervisorctl stop "runner-${runner_name}" 2>/dev/null || true - - echo "Removing configuration..." - rm -f "/etc/supervisor/conf.d/runner-${runner_name}.conf" - - echo "Deleting runner directory..." - rm -rf "$runner_dir" - - echo "Updating supervisor..." - supervisorctl reread - supervisorctl update - - echo "" - echo "✓ Runner '$runner_name' deleted successfully!" -} - -# 函数:查看 runner 日志 -logs_runner() { - local runner_name=$1 - local lines=${2:-50} - - local log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - if [ ! -f "$log_file" ]; then - echo "✗ Log file not found for runner '$runner_name'" - return 1 - fi - - echo "Showing last $lines lines of '$runner_name' logs:" - echo "-------------------------------------------" - tail -n "$lines" "$log_file" -} - -# 函数:实时查看日志 -follow_logs() { - local runner_name=$1 - local log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - if [ ! -f "$log_file" ]; then - echo "✗ Log file not found for runner '$runner_name'" - return 1 - fi - - echo "Following logs for '$runner_name' (Press Ctrl+C to exit):" - echo "-------------------------------------------" - tail -f "$log_file" -} - -# 函数:启动/停止/重启 runner -control_runner() { - local action=$1 - local runner_name=$2 - - case $action in - start|stop|restart) - echo "${action^}ing runner '$runner_name'..." - supervisorctl "$action" "runner-${runner_name}" - ;; - *) - echo "✗ Invalid action: $action" - return 1 - ;; - esac -} - -# 函数:显示所有 runner 状态 -status_all() { - echo "All Runners Status:" - echo "-------------------------------------------" - supervisorctl status | grep "^runner-" || echo "No runners running." - echo "" -} - -# 主菜单 -show_menu() { - echo "Choose an action:" - echo " 1) List all runners" - echo " 2) Show runner details" - echo " 3) Add new runner" - echo " 4) Delete runner" - echo " 5) Start runner" - echo " 6) Stop runner" - echo " 7) Restart runner" - echo " 8) View runner logs" - echo " 9) Follow runner logs (real-time)" - echo " 10) Show all runners status" - echo " 0) Exit" - echo "" -} - -# 主程序 -if [ $# -eq 0 ]; then - # 交互模式 - while true; do - show_menu - read -p "Enter your choice: " choice - echo "" - - case $choice in - 1) - list_runners - ;; - 2) - read -p "Enter runner name: " runner_name - show_runner "$runner_name" - ;; - 3) - echo "Starting registration process..." - /data/register.sh - ;; - 4) - read -p "Enter runner name to delete: " runner_name - delete_runner "$runner_name" - ;; - 5) - read -p "Enter runner name to start: " runner_name - control_runner start "$runner_name" - ;; - 6) - read -p "Enter runner name to stop: " runner_name - control_runner stop "$runner_name" - ;; - 7) - read -p "Enter runner name to restart: " runner_name - control_runner restart "$runner_name" - ;; - 8) - read -p "Enter runner name: " runner_name - read -p "Number of lines (default 50): " lines - logs_runner "$runner_name" "${lines:-50}" - ;; - 9) - read -p "Enter runner name: " runner_name - follow_logs "$runner_name" - ;; - 10) - status_all - ;; - 0) - echo "Goodbye!" - exit 0 - ;; - *) - echo "Invalid choice!" - ;; - esac - - echo "" - read -p "Press Enter to continue..." - clear - done -else - # 命令行模式 - case $1 in - list|ls) - list_runners - ;; - show|info) - show_runner "$2" - ;; - add|register) - /data/register.sh - ;; - delete|rm|remove) - delete_runner "$2" - ;; - start) - control_runner start "$2" - ;; - stop) - control_runner stop "$2" - ;; - restart) - control_runner restart "$2" - ;; - logs) - logs_runner "$2" "${3:-50}" - ;; - follow) - follow_logs "$2" - ;; - status) - status_all - ;; - *) - echo "Usage: $0 [command] [runner_name]" - echo "" - echo "Commands:" - echo " list - List all runners" - echo " show - Show runner details" - echo " add - Add new runner" - echo " delete - Delete a runner" - echo " start - Start a runner" - echo " stop - Stop a runner" - echo " restart - Restart a runner" - echo " logs [lines] - View runner logs" - echo " follow - Follow runner logs (real-time)" - echo " status - Show all runners status" - echo "" - echo "Or run without arguments for interactive mode." - exit 1 - ;; - esac -fi -``` - -### 🚀 部署步骤 - -#### 1. 设置脚本权限 - -```bash -chmod +x entrypoint.sh setup.sh register.sh manage.sh -``` - -#### 2. 构建并启动容器 +#### 3. 构建并启动容器 ```bash docker-compose build docker-compose up -d ``` -#### 3. 安装 Runner +#### 4. 安装 Runner ```bash docker-compose exec gitea-runner /data/setup.sh ``` -按照提示选择版本和架构。 +按照提示选择版本(默认 0.2.13)和架构(自动检测)。 -#### 4. 注册 Runner +#### 5. 注册 Runner ```bash docker-compose exec gitea-runner /data/register.sh @@ -1083,394 +138,139 @@ docker-compose exec gitea-runner /data/register.sh 输入你的 Gitea 实例 URL 和注册令牌。 -#### 5. 重启容器启动 Runner - -```bash -docker-compose restart -``` +Runner 注册后会自动启动,无需重启容器。 #### 6. 验证运行状态 ```bash -# 查看日志 +# 查看容器日志 docker-compose logs -f # 查看 runner 状态 -docker-compose exec gitea-runner /data/manage.sh list docker-compose exec gitea-runner /data/manage.sh status ``` --- -## 🚀 版本 2:Buildx 多架构版 +### Buildx 版部署 -### 📝 文件配置差异 +#### 1. 选择并进入预设目录 -Buildx 版本与标准版的主要区别在于以下文件: +```bash +# Ubuntu 22.04 版本(推荐) +cd docker-runner/presets/buildx-ubuntu-22/ -#### 1️⃣ Dockerfile(Buildx 版) - -```dockerfile -FROM ubuntu:22.04 - -# 设置环境变量避免交互式安装 -ENV DEBIAN_FRONTEND=noninteractive - -# 更新系统并安装必要软件 -RUN apt-get update && apt-get install -y \ - curl \ - git \ - python3 \ - python3-yaml \ - supervisor \ - ca-certificates \ - gnupg \ - lsb-release \ - qemu-user-static \ - binfmt-support \ - && rm -rf /var/lib/apt/lists/* - -# 安装 Docker(包含 Buildx 插件) -RUN curl -fsSL https://get.docker.com -o get-docker.sh && \ - sh get-docker.sh && \ - rm get-docker.sh - -# 验证安装 -RUN docker --version && \ - qemu-aarch64-static --version && \ - qemu-x86_64-static --version - -# 创建必要目录 -RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor - -# 设置工作目录 -WORKDIR /data - -# 使用自定义入口点 -ENTRYPOINT ["/data/entrypoint.sh"] +# 或 Arch Linux 版本 +cd docker-runner/presets/buildx-archlinux/ ``` -#### 2️⃣ docker-compose.yml(Buildx 版) +#### 2. (可选)配置代理 + +如果需要代理,编辑 `docker-compose.yml` 取消注释并修改代理地址: ```yaml -services: - gitea-runner: - build: . - container_name: gitea-runner - restart: unless-stopped - privileged: true - volumes: - - ./runner-data:/data - - ./setup.sh:/data/setup.sh:ro - - ./register.sh:/data/register.sh:ro - - ./manage.sh:/data/manage.sh:ro - - ./entrypoint.sh:/data/entrypoint.sh:ro - - /var/run/docker.sock:/var/run/docker.sock - - environment: - - TZ=Asia/Shanghai - - # 如果需要使用代理,取消下面的注释并修改为你的代理地址 - # 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP - - http_proxy=http://host.docker.internal:20122 - - https_proxy=http://host.docker.internal:20122 - - HTTP_PROXY=http://host.docker.internal:20122 - - HTTPS_PROXY=http://host.docker.internal:20122 - # - no_proxy=localhost,127.0.0.1 - - # Linux 系统需要取消下面的注释以支持 host.docker.internal - # extra_hosts: - # - "host.docker.internal:host-gateway" +environment: + - http_proxy=http://host.docker.internal:20122 + - https_proxy=http://host.docker.internal:20122 ``` -#### 3️⃣ entrypoint.sh(Buildx 版) - -```bash -#!/bin/bash -set -e - -echo "===================================" -echo "Gitea Runner Container Starting..." -echo "===================================" - -# 定义路径 -PERSISTENT_BIN="/data/bin" -RUNNER_PATH="$PERSISTENT_BIN/act_runner" -SYSTEM_LINK="/usr/local/bin/act_runner" - -# 创建必要目录 -mkdir -p /data/runners -mkdir -p "$PERSISTENT_BIN" -mkdir -p /data/buildx -mkdir -p /var/log/supervisor -mkdir -p /var/run - -# ============================================ -# 初始化 Docker Buildx 支持 -# ============================================ -echo "" -echo "Initializing Docker Buildx..." - -# 启动 Docker 守护进程(如果使用主机 socket 则跳过) -if [ -S /var/run/docker.sock ]; then - echo "✓ Using host Docker socket" -else - echo "Starting Docker daemon..." - dockerd > /var/log/dockerd.log 2>&1 & - sleep 5 -fi - -# 等待 Docker 就绪 -echo "Waiting for Docker daemon..." -for i in {1..30}; do - if docker info > /dev/null 2>&1; then - echo "✓ Docker daemon is ready" - break - fi - if [ $i -eq 30 ]; then - echo "✗ Docker daemon failed to start" - [ -f /var/log/dockerd.log ] && cat /var/log/dockerd.log - exit 1 - fi - sleep 1 -done - -# 注册 QEMU binfmt -echo "" -echo "Registering QEMU binary formats..." -update-binfmts --enable 2>/dev/null || { - echo "⚠ binfmt_misc not available, trying to mount..." - mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true - update-binfmts --enable -} - -# 验证多架构支持 -echo "Verifying multi-arch support..." -if docker run --rm arm64v8/alpine uname -m > /dev/null 2>&1; then - echo " ✓ arm64 support verified" -else - echo " ⚠ arm64 verification failed" -fi - -if docker run --rm amd64/alpine uname -m > /dev/null 2>&1; then - echo " ✓ amd64 support verified" -else - echo " ⚠ amd64 verification failed" -fi - -# 配置 Buildx -if [ ! -f "/data/buildx/.configured" ]; then - echo "" - echo "Setting up Buildx for the first time..." - - # 创建 BuildKit 配置 - cat > /data/buildx/buildkitd.toml </dev/null || \ - docker buildx use gitea-multiarch 2>/dev/null - - # 验证 - echo "Verifying Buildx..." - docker buildx inspect --bootstrap > /dev/null 2>&1 - - # 标记为已配置 - touch /data/buildx/.configured - - echo "✓ Buildx configured successfully!" - docker buildx inspect | grep "Platforms:" | head -1 -else - echo "✓ Buildx already configured" - - # 确保 builder 可用 - docker buildx use gitea-multiarch 2>/dev/null || { - echo "⚠ Recreating Buildx builder..." - docker buildx rm gitea-multiarch 2>/dev/null || true - docker buildx create \ - --name gitea-multiarch \ - --driver docker-container \ - --bootstrap \ - --use 2>/dev/null - } -fi - -echo "" - -# ============================================ -# 检查 act_runner 安装 -# ============================================ -# 创建主 supervisor 配置文件 -cat > /etc/supervisor/supervisord.conf < $RUNNER_PATH" - fi - - RUNNER_VERSION=$("$SYSTEM_LINK" --version 2>/dev/null || echo "unknown") - echo " Version: $RUNNER_VERSION" -elif [ -f "$SYSTEM_LINK" ]; then - echo "⚠ Found act_runner in system path, migrating to persistent storage..." - cp "$SYSTEM_LINK" "$RUNNER_PATH" - chmod +x "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo " ✓ Migrated to: $RUNNER_PATH" -else - echo "⚠ act_runner not installed yet!" - echo "" - echo "Please run the setup script first:" - echo " docker-compose exec gitea-runner /data/setup.sh" - echo "" - echo "Container is waiting..." - - while [ ! -f "$RUNNER_PATH" ] && [ ! -f "$SYSTEM_LINK" ]; do - sleep 10 - done - - if [ -f "$RUNNER_PATH" ]; then - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and linked!" - elif [ -f "$SYSTEM_LINK" ]; then - cp "$SYSTEM_LINK" "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and migrated!" - fi -fi - -# ============================================ -# 配置已注册的 Runners -# ============================================ -echo "" -echo "Scanning for registered runners..." -RUNNER_COUNT=0 - -if [ -d "/data/runners" ]; then - for runner_dir in /data/runners/*/; do - if [ -d "$runner_dir" ]; then - runner_name=$(basename "$runner_dir") - - if [ -f "$runner_dir/.runner" ] && [ -f "$runner_dir/config.yaml" ]; then - echo "Found runner: $runner_name" - - cat > "/etc/supervisor/conf.d/runner-${runner_name}.conf" < + +# 指定行数 +docker-compose exec gitea-runner /data/manage.sh logs 100 + +# 实时跟踪日志 +docker-compose exec gitea-runner /data/manage.sh follow +``` + +### Runner 控制 + +```bash +# 启动 runner +docker-compose exec gitea-runner /data/manage.sh start + +# 停止 runner +docker-compose exec gitea-runner /data/manage.sh stop + +# 重启 runner +docker-compose exec gitea-runner /data/manage.sh restart + +# 删除 runner +docker-compose exec gitea-runner /data/manage.sh delete +``` + +### 添加多个 Runners + +```bash +# 注册新的 runner(使用不同名称) +docker-compose exec gitea-runner /data/register.sh +``` + +### 交互式管理 + +```bash +# 运行交互式菜单 +docker-compose exec gitea-runner /data/manage.sh +``` + +--- + +## 🔧 Buildx 多架构构建示例 + +### 示例 1: 基础构建 + +在 Gitea Actions workflow 中使用: ```yaml name: Multi-Arch Build @@ -1498,9 +298,9 @@ jobs: push: true ``` -#### 示例 2:Go 应用优化构建 +### 示例 2: Go 应用优化构建 -使用交叉编译可以大幅提升构建速度: +使用交叉编译可以大幅提升构建速度: ```dockerfile FROM --platform=$BUILDPLATFORM golang:1.21 AS builder @@ -1514,6 +314,20 @@ COPY --from=builder /app/app /app CMD ["/app"] ``` +### 示例 3: 启用构建缓存 + +```yaml +- name: Build with cache + uses: docker/build-push-action@v4 + with: + context: . + platforms: linux/amd64,linux/arm64 + cache-from: type=registry,ref=myimage:buildcache + cache-to: type=registry,ref=myimage:buildcache,mode=max + tags: myimage:latest + push: true +``` + --- ## ⚖️ 版本对比 @@ -1523,8 +337,8 @@ CMD ["/app"] | 功能 | 标准版 | Buildx 版 | | ---------------- | ------- | --------- | | 基础 Runner 功能 | ✅ | ✅ | -| arm64 原生构建 | ✅ | ✅ | -| amd64 模拟构建 | ❌ | ✅ | +| 当前架构原生构建 | ✅ | ✅ | +| 跨架构模拟构建 | ❌ | ✅ | | 多架构镜像 | ❌ | ✅ | | Buildx 支持 | ❌ | ✅ | | QEMU 内置 | ❌ | ✅ | @@ -1534,21 +348,21 @@ CMD ["/app"] | 启动时间 | 5-10 秒 | 15-20 秒 | | 复杂度 | 简单 | 中等 | -### 性能对比(Buildx 版) +### 性能对比(Buildx 版) -在 ARM64 主机上使用 Buildx 构建不同架构的性能: +在 ARM64 主机上使用 Buildx 构建不同架构的性能: -| 项目类型 | ARM64 (原生) | AMD64 (QEMU) | 双架构并行 | -| -------------- | ------------ | ------------ | ---------- | -| Alpine 镜像 | 5s | 15s | 18s | -| Node.js 应用 | 2min | 8min | 9min | -| Go 应用 | 1.5min | 6min | 7min | -| Go(交叉编译) | 1min | 1.5min | 2min | +| 项目类型 | ARM64(原生) | AMD64(QEMU) | 双架构并行 | +| ------------ | ----------- | ----------- | ---------- | +| Alpine 镜像 | 5s | 15s | 18s | +| Node.js 应用 | 2min | 8min | 9min | +| Go 应用 | 1.5min | 6min | 7min | +| Go(交叉编译) | 1min | 1.5min | 2min | -**关键发现:** +**关键发现:** -- 🏆 ARM64 原生构建最快 -- 🐌 AMD64 模拟慢 3-4 倍(QEMU) +- 🏆 原生架构构建最快 +- 🐌 跨架构模拟慢 3-4 倍(QEMU) - ⚡ 交叉编译比纯 QEMU 快 4 倍 - 💾 使用缓存可提速 80-90% @@ -1556,14 +370,14 @@ CMD ["/app"] #### 选择标准版 -- ✅ 只在 arm64 上运行 arm64 应用 +- ✅ 只需要在当前架构上运行应用 - ✅ 不需要发布多架构镜像 - ✅ 追求简单和轻量 - ✅ 不需要 Docker-in-Docker #### 选择 Buildx 版 -- ✅ 需要构建 amd64 + arm64 镜像 +- ✅ 需要构建多架构镜像(如 amd64 + arm64) - ✅ 发布到 Docker Hub 等公共仓库 - ✅ 跨平台应用开发 - ✅ CI/CD 需要多架构支持 @@ -1572,19 +386,18 @@ CMD ["/app"] ## ❓ 常见问题 -### Q1: 如何更新 Runner 版本? +### Q1: 如何更新 Runner 版本? ```bash docker-compose exec gitea-runner /data/setup.sh -# 脚本会询问是否升级 +# 脚本会检测到已安装并询问是否升级 ``` -### Q2: 如何添加多个 Runners? +### Q2: 如何添加多个 Runners? ```bash -# 多次运行注册脚本 +# 多次运行注册脚本,每次使用不同名称 docker-compose exec gitea-runner /data/register.sh -# 每次使用不同名称 # 查看所有 runners docker-compose exec gitea-runner /data/manage.sh list @@ -1592,14 +405,17 @@ docker-compose exec gitea-runner /data/manage.sh list ### Q3: 容器启动失败 "exec format error" -**原因:** Windows 换行符问题 +**原因:** Windows 换行符问题(CRLF vs LF) -**解决:** +**解决:** ```bash -# 转换换行符 -sed -i 's/\r$//' *.sh -chmod +x *.sh +# 方法 1: 使用提供的检查工具 +cd docker-runner/presets// +../../common/check_crlf.sh + +# 方法 2: 手动转换 +sed -i 's/\r$//' ../../common/*.sh # 重新构建 docker-compose down @@ -1607,89 +423,36 @@ docker-compose build --no-cache docker-compose up -d ``` -### Q4: 如何完全重置? +### Q4: 如何完全重置? ```bash +# 停止并删除容器和卷 docker-compose down -v + +# 删除数据目录 rm -rf runner-data + +# 重新构建 docker-compose build --no-cache docker-compose up -d ``` -### Q5: 如何清理 Docker 资源? - -#### 🧹 清理未使用的镜像 - -```bash -# 清理悬空镜像(dangling images) -docker image prune - -# 清理所有未使用的镜像 -docker image prune -a - -# 查看镜像占用空间 -docker system df -``` - -#### 🗑️ 清理 Buildx 缓存(仅 Buildx 版) - -```bash -# 清理构建缓存(保留 builder) -docker buildx prune - -# 清理所有构建缓存 -docker buildx prune -a -f - -# 删除 builder(会自动清理相关容器和镜像) -docker buildx rm gitea-multiarch -``` - -#### 🔄 完整清理流程 - -```bash -# 1. 停止所有容器 -docker-compose down - -# 2. 清理 Buildx(如果使用 Buildx 版) -docker buildx rm gitea-multiarch - -# 3. 清理未使用的镜像 -docker image prune -a - -# 4. 清理系统(慎用!会清理所有未使用资源) -docker system prune -a --volumes - -# 5. 查看清理效果 -docker system df -``` - -#### ⚠️ 注意事项 - -- `docker system prune -a` 会删除**所有未使用的镜像**,包括其他项目的 -- 如果只想清理 Gitea Runner 相关资源,建议单独删除: - -```bash - docker rmi buildx-gitea-runner:latest - docker rmi arm64v8/alpine:latest - docker rmi moby/buildkit:buildx-stable-1 -``` - -### Q6: 如何查看日志? +### Q5: 如何查看日志? ```bash # 容器日志 docker-compose logs -f # Runner 日志 -docker-compose exec gitea-runner /data/manage.sh logs runner-name +docker-compose exec gitea-runner /data/manage.sh logs # 实时跟踪日志 -docker-compose exec gitea-runner /data/manage.sh follow runner-name +docker-compose exec gitea-runner /data/manage.sh follow ``` -### Q7: Buildx 版 - 构建速度慢? +### Q6: Buildx 版 - 构建速度慢? -**优化方法:** +**优化方法:** #### 1. 启用缓存 @@ -1704,20 +467,22 @@ docker-compose exec gitea-runner /data/manage.sh follow runner-name #### 2. 使用交叉编译 +对于 Go、Rust 等支持交叉编译的语言,优先使用交叉编译而非 QEMU 模拟: + ```dockerfile FROM --platform=$BUILDPLATFORM golang:1.21 AS builder ARG TARGETOS TARGETARCH -RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app ``` #### 3. 按需构建 ```yaml -# 开发分支只构建 arm64,生产分支构建双架构 +# 开发分支只构建当前架构,生产分支构建双架构 platforms: ${{ github.ref == 'refs/heads/main' && 'linux/amd64,linux/arm64' || 'linux/arm64' }} ``` -### Q8: Buildx 版 - 如何验证 Buildx? +### Q7: Buildx 版 - 如何验证 Buildx? ```bash # 进入容器 @@ -1730,6 +495,95 @@ docker buildx ls echo 'FROM alpine' | docker buildx build --platform linux/amd64,linux/arm64 - ``` +### Q8: 如何清理 Docker 资源? + +#### 清理未使用的镜像 + +```bash +# 清理悬空镜像(dangling images) +docker image prune + +# 清理所有未使用的镜像 +docker image prune -a + +# 查看镜像占用空间 +docker system df +``` + +#### 清理 Buildx 缓存(仅 Buildx 版) + +```bash +# 进入容器 +docker-compose exec gitea-runner bash + +# 清理构建缓存(保留 builder) +docker buildx prune + +# 清理所有构建缓存 +docker buildx prune -a -f + +# 删除 builder(会自动清理相关容器和镜像) +docker buildx rm gitea-multiarch +``` + +#### 完整清理流程 + +```bash +# 1. 停止所有容器 +docker-compose down + +# 2. 清理 Buildx(如果使用 Buildx 版) +docker-compose exec gitea-runner docker buildx rm gitea-multiarch + +# 3. 清理未使用的镜像 +docker image prune -a + +# 4. 清理系统(慎用!会清理所有未使用资源) +docker system prune -a --volumes + +# 5. 查看清理效果 +docker system df +``` + +⚠️ **注意:** `docker system prune -a` 会删除所有未使用的镜像,包括其他项目的。 + +### Q9: 数据持久化在哪里? + +所有数据持久化在 `runner-data/` 目录: + +```txt +runner-data/ +├── bin/ +│ └── act_runner # Runner 可执行文件(持久化) +├── runners/ # Runner 配置目录 +│ └── / +│ ├── .runner # 注册信息 +│ ├── config.yaml # 配置文件 +│ └── cache/ # 构建缓存 +└── buildx/ # Buildx 配置(仅 Buildx 版) + └── .configured +``` + +容器重启或重建后,数据不会丢失。 + +### Q10: 如何切换不同预设? + +```bash +# 1. 停止当前容器 +cd docker-runner/presets// +docker-compose down + +# 2. 切换到新预设 +cd ../buildx-ubuntu-22/ + +# 3. 复制数据目录(可选,保留旧数据) +cp -r ../standard-ubuntu-22/runner-data . + +# 4. 启动新预设 +docker-compose build +docker-compose up -d +``` + --- ## 📚 参考资源 @@ -1737,6 +591,7 @@ echo 'FROM alpine' | docker buildx build --platform linux/amd64,linux/arm64 - - 📖 [Gitea Actions 官方文档](https://docs.gitea.com/usage/actions/overview) - 🚀 [Gitea Runner 下载](https://dl.gitea.com/act_runner/) - 🐳 [Docker Buildx 文档](https://docs.docker.com/reference/cli/docker/buildx/) +- 🔧 [Act Runner GitHub](https://gitea.com/gitea/act_runner) --- diff --git a/docker-runner/buildx/register.sh b/docker-runner/buildx/register.sh deleted file mode 100644 index 9bdbada..0000000 --- a/docker-runner/buildx/register.sh +++ /dev/null @@ -1,321 +0,0 @@ -#!/bin/bash -set -e - -echo "==========================================" -echo " Gitea Runner Registration Script " -echo "==========================================" -echo "" - -# 检查 act_runner 是否安装 -if ! command -v act_runner &> /dev/null; then - echo "✗ act_runner is not installed!" - echo "" - echo "Please run the setup script first:" - echo " docker-compose exec gitea-runner /data/setup.sh" - exit 1 -fi - -echo "✓ act_runner found: $(act_runner --version)" -echo "" - -# 获取注册信息并验证 -while true; do - read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE - - # 验证 URL 格式 - if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then - echo "✗ Error: URL must start with http:// or https://" - echo "" - continue - fi - - # 移除末尾的斜杠 - GITEA_INSTANCE="${GITEA_INSTANCE%/}" - echo "✓ URL validated: $GITEA_INSTANCE" - break -done - -read -p "Enter registration token: " GITEA_TOKEN - -if [ -z "$GITEA_TOKEN" ]; then - echo "✗ Error: Token cannot be empty!" - exit 1 -fi - -read -p "Enter runner name (default: docker-runner): " RUNNER_NAME -RUNNER_NAME=${RUNNER_NAME:-docker-runner} - -# 多个 label(逗号分隔,无空格) -# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18 -read -p "Enter runner labels (default: ubuntu-22.04:host://ubuntu:22.04): " RUNNER_LABELS -RUNNER_LABELS=${RUNNER_LABELS:-ubuntu-22.04:host://ubuntu:22.04} - -# 创建 runner 目录 -RUNNER_DIR="/data/runners/${RUNNER_NAME}" -mkdir -p "$RUNNER_DIR" -cd "$RUNNER_DIR" - -echo "" -echo "Registration Information:" -echo " Instance: $GITEA_INSTANCE" -echo " Name: $RUNNER_NAME" -echo " Labels: $RUNNER_LABELS" -echo " Directory: $RUNNER_DIR" -echo "" - -# 检查是否已经注册 -if [ -f ".runner" ] || [ -f "config.yaml" ]; then - echo "⚠ Runner already exists in this directory!" - read -p "Do you want to re-register? This will overwrite existing configuration. (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Registration cancelled." - exit 0 - fi - - echo "Cleaning up existing runner..." - - # 停止现有 runner - echo "Stopping existing runner..." - supervisorctl stop "runner-${RUNNER_NAME}" 2>/dev/null || true - - # 删除 supervisor 配置 - rm -f "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" - - # 重新加载 supervisor - supervisorctl reread 2>/dev/null || true - supervisorctl update 2>/dev/null || true - - # 删除日志 - rm -f "/var/log/supervisor/runner-${RUNNER_NAME}".*.log* - - # 删除旧配置和缓存 - rm -f .runner config.yaml - rm -rf cache -fi - -# 执行注册 -echo "" -echo "Registering runner..." -act_runner register \ - --instance "$GITEA_INSTANCE" \ - --token "$GITEA_TOKEN" \ - --name "$RUNNER_NAME" \ - --labels "$RUNNER_LABELS" \ - --no-interactive - -if [ ! -f ".runner" ]; then - echo "" - echo "✗ Registration failed! .runner file not created." - exit 1 -fi - -echo "✓ Registration successful!" - -# 生成配置文件 -echo "" -echo "Generating config.yaml..." -act_runner generate-config > config.yaml - -echo "✓ Configuration file generated!" - -# 创建缓存目录 -mkdir -p cache - -# 使用 Python 修改配置(最可靠的方法) -echo "" -echo "Configuring runner settings..." - -if command -v python3 &> /dev/null; then - python3 << PYEOF -import yaml -import sys - -try: - # 读取生成的配置 - with open('config.yaml', 'r') as f: - config = yaml.safe_load(f) - - # 读取 .runner 获取实际注册的 labels - import json - with open('.runner', 'r') as f: - runner_data = json.load(f) - - # 使用 .runner 中的 labels(这是实际注册的) - registered_labels = runner_data.get('labels', []) - - # 修改配置 - if 'runner' not in config: - config['runner'] = {} - - # 使用实际注册的 labels - config['runner']['labels'] = registered_labels - config['runner']['capacity'] = 2 - - # 启用缓存 - if 'cache' not in config: - config['cache'] = {} - config['cache']['enabled'] = True - config['cache']['dir'] = './cache' - - # 保存配置 - with open('config.yaml', 'w') as f: - yaml.dump(config, f, default_flow_style=False, sort_keys=False) - - print("✓ Configuration updated using Python") - print(f" - Labels: {registered_labels}") - print(f" - Capacity: 2") - print(f" - Cache enabled: ./cache") - sys.exit(0) - -except Exception as e: - print(f"✗ Python configuration failed: {e}", file=sys.stderr) - sys.exit(1) -PYEOF - - PYTHON_EXIT=$? - - if [ $PYTHON_EXIT -ne 0 ]; then - echo "" - echo "⚠ Python configuration failed, using basic sed..." - - # 基本的 sed 修改(只修改简单的值,不动 labels) - sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true - sed -i 's/enabled: false/enabled: true/g' config.yaml || true - sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true - - echo "✓ Basic configuration applied" - echo " Note: Please manually verify labels in config.yaml match .runner" - fi -else - echo "⚠ Python3 not found, applying basic configuration..." - - # 基本的 sed 修改 - sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true - sed -i 's/enabled: false/enabled: true/g' config.yaml || true - sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true - - echo "✓ Basic configuration applied" - echo " Note: Labels will use act_runner defaults" -fi - -# 验证配置文件 -echo "" -echo "Validating configuration..." - -# 检查 YAML 语法 -if command -v python3 &> /dev/null; then - python3 << PYEOF -import yaml -import sys -try: - with open('config.yaml', 'r') as f: - yaml.safe_load(f) - print("✓ config.yaml syntax is valid") - sys.exit(0) -except Exception as e: - print(f"✗ config.yaml syntax error: {e}", file=sys.stderr) - sys.exit(1) -PYEOF - - if [ $? -ne 0 ]; then - echo "" - echo "✗ Configuration file has syntax errors!" - echo " Backup available at: config.yaml.bak" - exit 1 - fi -fi - -# 显示配置摘要 -echo "" -echo "Configuration Summary:" -echo "-------------------------------------------" -echo ".runner labels:" -cat .runner | grep -A 10 '"labels"' | head -15 -echo "" -echo "config.yaml labels:" -grep -A 5 "^ labels:" config.yaml | head -10 - -# 创建 supervisor 配置 -echo "" -echo "Creating supervisor configuration..." -cat > "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" </dev/null || \ - supervisorctl start "runner-${RUNNER_NAME}" - -# 等待启动 -sleep 3 - -# 显示状态 -RUNNER_STATUS=$(supervisorctl status "runner-${RUNNER_NAME}" 2>/dev/null || echo "UNKNOWN") - -echo "" -echo "==========================================" -echo "✓ Runner registered and started!" -echo "==========================================" -echo "" -echo "Runner Information:" -echo " Name: $RUNNER_NAME" -echo " Directory: $RUNNER_DIR" -echo " Status: $RUNNER_STATUS" -echo "" -echo "Configuration files:" -echo " .runner: $(ls -lh .runner 2>/dev/null | awk '{print $5}' || echo 'N/A')" -echo " config.yaml: $(ls -lh config.yaml 2>/dev/null | awk '{print $5}' || echo 'N/A')" -echo "" -echo "Useful commands:" -echo " View logs: docker-compose exec gitea-runner /data/manage.sh logs ${RUNNER_NAME}" -echo " Follow logs: docker-compose exec gitea-runner /data/manage.sh follow ${RUNNER_NAME}" -echo " Check status: docker-compose exec gitea-runner /data/manage.sh status" -echo " Restart: docker-compose exec gitea-runner /data/manage.sh restart ${RUNNER_NAME}" -echo "" - -# 显示最近的日志 -if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" ]; then - echo "Recent logs:" - echo "-------------------------------------------" - tail -n 20 "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" 2>/dev/null || echo "No logs yet" - echo "" -fi - -# 检查是否有错误 -if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" ]; then - # 只查找 error/fatal/panic 级别的日志 - ERR_CONTENT=$(grep -E 'level=(error|fatal|panic)' \ - "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" | tail -n 5 2>/dev/null) - - if [ -n "$ERR_CONTENT" ]; then - echo "❌ Recent errors detected:" - echo "-------------------------------------------" - echo "$ERR_CONTENT" - echo "" - echo "Check full error log with:" - echo " docker-compose exec gitea-runner cat /var/log/supervisor/runner-${RUNNER_NAME}.err.log" - fi -fi diff --git a/docker-runner/buildx/check_crlf.sh b/docker-runner/common/check_crlf.sh similarity index 100% rename from docker-runner/buildx/check_crlf.sh rename to docker-runner/common/check_crlf.sh diff --git a/docker-runner/buildx/entrypoint.sh b/docker-runner/common/entrypoint.sh similarity index 53% rename from docker-runner/buildx/entrypoint.sh rename to docker-runner/common/entrypoint.sh index 5c3517a..9a39bc0 100644 --- a/docker-runner/buildx/entrypoint.sh +++ b/docker-runner/common/entrypoint.sh @@ -10,111 +10,134 @@ PERSISTENT_BIN="/data/bin" RUNNER_PATH="$PERSISTENT_BIN/act_runner" SYSTEM_LINK="/usr/local/bin/act_runner" +# 读取环境变量配置 +ENABLE_BUILDX="${ENABLE_BUILDX:-false}" +BINFMT_METHOD="${BINFMT_METHOD:-update-binfmts}" # update-binfmts 或 tonistiigi + # 创建必要目录 mkdir -p /data/runners mkdir -p "$PERSISTENT_BIN" -mkdir -p /data/buildx mkdir -p /var/log/supervisor mkdir -p /var/run # ============================================ -# 初始化 Docker Buildx 支持 +# 初始化 Docker Buildx 支持(可选) # ============================================ -echo "" -echo "Initializing Docker Buildx..." - -# 启动 Docker 守护进程(如果使用主机 socket 则跳过) -if [ -S /var/run/docker.sock ]; then - echo "✓ Using host Docker socket" -else - echo "Starting Docker daemon..." - dockerd > /var/log/dockerd.log 2>&1 & - sleep 5 -fi - -# 等待 Docker 就绪 -echo "Waiting for Docker daemon..." -for i in {1..30}; do - if docker info > /dev/null 2>&1; then - echo "✓ Docker daemon is ready" - break - fi - if [ $i -eq 30 ]; then - echo "✗ Docker daemon failed to start" - [ -f /var/log/dockerd.log ] && cat /var/log/dockerd.log - exit 1 - fi - sleep 1 -done - -# 注册 QEMU binfmt -echo "" -echo "Registering QEMU binary formats..." -update-binfmts --enable 2>/dev/null || { - echo "⚠ binfmt_misc not available, trying to mount..." - mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true - update-binfmts --enable -} - -# 验证多架构支持 -echo "Verifying multi-arch support..." -if docker run --rm arm64v8/alpine uname -m > /dev/null 2>&1; then - echo " ✓ arm64 support verified" -else - echo " ⚠ arm64 verification failed" -fi - -if docker run --rm amd64/alpine uname -m > /dev/null 2>&1; then - echo " ✓ amd64 support verified" -else - echo " ⚠ amd64 verification failed" -fi - -# 配置 Buildx -if [ ! -f "/data/buildx/.configured" ]; then +if [ "$ENABLE_BUILDX" = "true" ]; then echo "" - echo "Setting up Buildx for the first time..." + echo "Initializing Docker Buildx..." + mkdir -p /data/buildx - # 创建 BuildKit 配置 - cat > /data/buildx/buildkitd.toml < /var/log/dockerd.log 2>&1 & + sleep 5 + fi + + # 等待 Docker 就绪 + echo "Waiting for Docker daemon..." + for i in {1..30}; do + if docker info > /dev/null 2>&1; then + echo "✓ Docker daemon is ready" + break + fi + if [ $i -eq 30 ]; then + echo "✗ Docker daemon failed to start" + [ -f /var/log/dockerd.log ] && cat /var/log/dockerd.log + exit 1 + fi + sleep 1 + done + + # 注册 QEMU binfmt + echo "" + echo "Registering QEMU binary formats..." + + if [ "$BINFMT_METHOD" = "tonistiigi" ]; then + # 使用 tonistiigi/binfmt(更可靠) + if docker run --privileged --rm tonistiigi/binfmt --install arm64,amd64 > /var/log/binfmt-install.log 2>&1; then + echo "✓ Installed binfmt via tonistiigi/binfmt" + grep -m1 "Installed" /var/log/binfmt-install.log || true + else + echo "⚠ binfmt install via tonistiigi/binfmt failed, trying local tools..." + if command -v update-binfmts > /dev/null 2>&1; then + update-binfmts --enable 2>/dev/null || true + else + echo "⚠ update-binfmts not available; multi-arch emulation may be limited" + fi + fi + else + # 使用 update-binfmts(传统方法) + update-binfmts --enable 2>/dev/null || { + echo "⚠ binfmt_misc not available, trying to mount..." + mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true + update-binfmts --enable + } + fi + + # 验证多架构支持 + echo "Verifying multi-arch support..." + if docker run --rm arm64v8/alpine uname -m > /dev/null 2>&1; then + echo " ✓ arm64 support verified" + else + echo " ⚠ arm64 verification failed" + fi + + if docker run --rm amd64/alpine uname -m > /dev/null 2>&1; then + echo " ✓ amd64 support verified" + else + echo " ⚠ amd64 verification failed" + fi + + # 配置 Buildx + if [ ! -f "/data/buildx/.configured" ]; then + echo "" + echo "Setting up Buildx for the first time..." + + # 创建 BuildKit 配置 + cat > /data/buildx/buildkitd.toml </dev/null || \ - docker buildx use gitea-multiarch 2>/dev/null - - # 验证 - echo "Verifying Buildx..." - docker buildx inspect --bootstrap > /dev/null 2>&1 - - # 标记为已配置 - touch /data/buildx/.configured - - echo "✓ Buildx configured successfully!" - docker buildx inspect | grep "Platforms:" | head -1 -else - echo "✓ Buildx already configured" - - # 确保 builder 可用 - docker buildx use gitea-multiarch 2>/dev/null || { - echo "⚠ Recreating Buildx builder..." - docker buildx rm gitea-multiarch 2>/dev/null || true + # 创建 Buildx builder docker buildx create \ --name gitea-multiarch \ --driver docker-container \ --bootstrap \ - --use 2>/dev/null - } -fi + --use \ + --config /data/buildx/buildkitd.toml 2>/dev/null || \ + docker buildx use gitea-multiarch 2>/dev/null -echo "" + # 验证 + echo "Verifying Buildx..." + docker buildx inspect --bootstrap > /dev/null 2>&1 + + # 标记为已配置 + touch /data/buildx/.configured + + echo "✓ Buildx configured successfully!" + docker buildx inspect | grep "Platforms:" | head -1 + else + echo "✓ Buildx already configured" + + # 确保 builder 可用 + docker buildx use gitea-multiarch 2>/dev/null || { + echo "⚠ Recreating Buildx builder..." + docker buildx rm gitea-multiarch 2>/dev/null || true + docker buildx create \ + --name gitea-multiarch \ + --driver docker-container \ + --bootstrap \ + --use 2>/dev/null + } + fi + + echo "" +fi # ============================================ # 检查 act_runner 安装 diff --git a/docker-runner/buildx/manage.sh b/docker-runner/common/manage.sh similarity index 100% rename from docker-runner/buildx/manage.sh rename to docker-runner/common/manage.sh diff --git a/docker-runner/standard/register.sh b/docker-runner/common/register.sh similarity index 97% rename from docker-runner/standard/register.sh rename to docker-runner/common/register.sh index 9bdbada..b49efef 100644 --- a/docker-runner/standard/register.sh +++ b/docker-runner/common/register.sh @@ -47,8 +47,9 @@ RUNNER_NAME=${RUNNER_NAME:-docker-runner} # 多个 label(逗号分隔,无空格) # ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18 -read -p "Enter runner labels (default: ubuntu-22.04:host://ubuntu:22.04): " RUNNER_LABELS -RUNNER_LABELS=${RUNNER_LABELS:-ubuntu-22.04:host://ubuntu:22.04} +DEFAULT_LABEL="${DEFAULT_RUNNER_LABEL:-ubuntu-22.04:host://ubuntu:22.04}" +read -p "Enter runner labels (default: $DEFAULT_LABEL): " RUNNER_LABELS +RUNNER_LABELS=${RUNNER_LABELS:-$DEFAULT_LABEL} # 创建 runner 目录 RUNNER_DIR="/data/runners/${RUNNER_NAME}" diff --git a/docker-runner/buildx/setup.sh b/docker-runner/common/setup.sh similarity index 100% rename from docker-runner/buildx/setup.sh rename to docker-runner/common/setup.sh diff --git a/docker-runner/presets/buildx-archlinux/Dockerfile b/docker-runner/presets/buildx-archlinux/Dockerfile new file mode 100644 index 0000000..2b59e67 --- /dev/null +++ b/docker-runner/presets/buildx-archlinux/Dockerfile @@ -0,0 +1,68 @@ +FROM archlinux:latest + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# 初始化密钥和软件源 +RUN pacman-key --init && \ + pacman-key --populate archlinux && \ + sed -i 's/^#ParallelDownloads/ParallelDownloads/' /etc/pacman.conf && \ + printf "\n[archlinuxcn]\nServer = https://mirrors.ustc.edu.cn/archlinuxcn/\$arch\n" >> /etc/pacman.conf && \ + pacman -Syy --noconfirm + +# 安装基础工具、Buildx 支持和开发环境 +RUN pacman -Syu --noconfirm && \ + pacman -S --noconfirm --disable-download-timeout archlinuxcn-keyring && \ + pacman -S --noconfirm --needed \ + base-devel \ + ca-certificates \ + clang \ + lld \ + libc++ \ + libc++abi \ + cmake \ + ninja \ + curl \ + git \ + python \ + python-pyyaml \ + python-pip \ + paru \ + conan \ + sudo \ + vim \ + supervisor \ + qemu-user-static \ + qemu-user-static-binfmt \ + docker \ + docker-buildx \ + && pacman -Scc --noconfirm + +# AUR 用户(paru 需非 root 运行) +RUN useradd -m aur && \ + echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur && \ + chmod 0440 /etc/sudoers.d/aur + +# 安装额外的 AUR 工具 +USER aur +WORKDIR /home/aur +RUN paru -S --noconfirm --needed --noprogressbar llvm-mingw-w64-toolchain-ucrt-bin && \ + paru -Scc --noconfirm && \ + rm -rf ~/.cache/paru + +# 切换回 root +USER root +WORKDIR /root + +# 验证 qemu 和 docker 安装 +RUN qemu-aarch64-static --version && \ + qemu-x86_64-static --version && \ + docker --version + +# 创建必要目录 +RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor + +# 设置工作目录 +WORKDIR /data + +# 使用自定义入口点 +ENTRYPOINT ["/data/entrypoint.sh"] diff --git a/docker-runner/presets/buildx-archlinux/docker-compose.yml b/docker-runner/presets/buildx-archlinux/docker-compose.yml new file mode 100644 index 0000000..18d146e --- /dev/null +++ b/docker-runner/presets/buildx-archlinux/docker-compose.yml @@ -0,0 +1,35 @@ +services: + gitea-runner: + build: . + container_name: gitea-runner-buildx-archlinux + restart: unless-stopped + network_mode: "host" # 使用宿主机网络 + privileged: true # Buildx 需要 privileged 模式 + volumes: + - ./runner-data:/data + - ../../common/setup.sh:/data/setup.sh:ro + - ../../common/register.sh:/data/register.sh:ro + - ../../common/manage.sh:/data/manage.sh:ro + - ../../common/check_crlf.sh:/data/check_crlf.sh:ro + - ../../common/entrypoint.sh:/data/entrypoint.sh:ro + - /var/run/docker.sock:/var/run/docker.sock + + environment: + - TZ=Asia/Shanghai + + # Arch Linux Buildx 配置 - 使用 tonistiigi/binfmt + - ENABLE_BUILDX=true + - BINFMT_METHOD=tonistiigi + - DEFAULT_RUNNER_LABEL=archlinux:host://archlinux:latest,company-server:host://archlinux:latest,buildx-archlinux:host://archlinux:latest + + # 如果需要使用代理,取消下面的注释并修改为你的代理地址 + # 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP + # - http_proxy=http://host.docker.internal:20122 + # - https_proxy=http://host.docker.internal:20122 + # - HTTP_PROXY=http://host.docker.internal:20122 + # - HTTPS_PROXY=http://host.docker.internal:20122 + # - no_proxy=localhost,127.0.0.1 + + # Linux 系统需要取消下面的注释以支持 host.docker.internal + # extra_hosts: + # - "host.docker.internal:host-gateway" diff --git a/docker-runner/buildx/Dockerfile b/docker-runner/presets/buildx-ubuntu-22/Dockerfile similarity index 100% rename from docker-runner/buildx/Dockerfile rename to docker-runner/presets/buildx-ubuntu-22/Dockerfile diff --git a/docker-runner/buildx/docker-compose.yml b/docker-runner/presets/buildx-ubuntu-22/docker-compose.yml similarity index 57% rename from docker-runner/buildx/docker-compose.yml rename to docker-runner/presets/buildx-ubuntu-22/docker-compose.yml index b45e63d..02729ea 100644 --- a/docker-runner/buildx/docker-compose.yml +++ b/docker-runner/presets/buildx-ubuntu-22/docker-compose.yml @@ -1,21 +1,27 @@ services: gitea-runner: build: . - container_name: gitea-runner + container_name: gitea-runner-buildx-ubuntu-22 restart: unless-stopped network_mode: "host" # 使用宿主机网络 - privileged: true + privileged: true # Buildx 需要 privileged 模式 volumes: - ./runner-data:/data - - ./setup.sh:/data/setup.sh:ro - - ./register.sh:/data/register.sh:ro - - ./manage.sh:/data/manage.sh:ro - - ./entrypoint.sh:/data/entrypoint.sh:ro + - ../../common/setup.sh:/data/setup.sh:ro + - ../../common/register.sh:/data/register.sh:ro + - ../../common/manage.sh:/data/manage.sh:ro + - ../../common/check_crlf.sh:/data/check_crlf.sh:ro + - ../../common/entrypoint.sh:/data/entrypoint.sh:ro - /var/run/docker.sock:/var/run/docker.sock environment: - TZ=Asia/Shanghai + # Buildx 配置 - 启用多架构构建 + - ENABLE_BUILDX=true + - BINFMT_METHOD=update-binfmts + - DEFAULT_RUNNER_LABEL=ubuntu-22.04:host://ubuntu:22.04,company-server:host://ubuntu:22.04,buildx-ubuntu-22:host://ubuntu:22.04 + # 如果需要使用代理,取消下面的注释并修改为你的代理地址 # 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP # - http_proxy=http://host.docker.internal:20122 diff --git a/docker-runner/standard/Dockerfile b/docker-runner/presets/standard-ubuntu-22/Dockerfile similarity index 100% rename from docker-runner/standard/Dockerfile rename to docker-runner/presets/standard-ubuntu-22/Dockerfile diff --git a/docker-runner/standard/docker-compose.yml b/docker-runner/presets/standard-ubuntu-22/docker-compose.yml similarity index 63% rename from docker-runner/standard/docker-compose.yml rename to docker-runner/presets/standard-ubuntu-22/docker-compose.yml index 73e42e3..fa6a5fb 100644 --- a/docker-runner/standard/docker-compose.yml +++ b/docker-runner/presets/standard-ubuntu-22/docker-compose.yml @@ -1,20 +1,24 @@ services: gitea-runner: build: . - container_name: gitea-runner + container_name: gitea-runner-standard-ubuntu-22 restart: unless-stopped network_mode: "host" # 使用宿主机网络 volumes: - ./runner-data:/data - - ./setup.sh:/data/setup.sh:ro - - ./register.sh:/data/register.sh:ro - - ./manage.sh:/data/manage.sh:ro - - ./entrypoint.sh:/data/entrypoint.sh:ro + - ../../common/setup.sh:/data/setup.sh:ro + - ../../common/register.sh:/data/register.sh:ro + - ../../common/manage.sh:/data/manage.sh:ro + - ../../common/entrypoint.sh:/data/entrypoint.sh:ro - /var/run/docker.sock:/var/run/docker.sock environment: - TZ=Asia/Shanghai + # Standard 配置 - 不启用 Buildx + - ENABLE_BUILDX=false + - DEFAULT_RUNNER_LABEL=ubuntu-22.04:host://ubuntu:22.04,company-server:host://ubuntu:22.04,standard-ubuntu-22:host://ubuntu:22.04 + # 如果需要使用代理,取消下面的注释并修改为你的代理地址 # 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP # - http_proxy=http://host.docker.internal:20122 @@ -26,4 +30,3 @@ services: # Linux 系统需要取消下面的注释以支持 host.docker.internal # extra_hosts: # - "host.docker.internal:host-gateway" - diff --git a/docker-runner/standard/entrypoint.sh b/docker-runner/standard/entrypoint.sh deleted file mode 100644 index b7d1267..0000000 --- a/docker-runner/standard/entrypoint.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash -set -e - -echo "===================================" -echo "Gitea Runner Container Starting..." -echo "===================================" - -# 定义路径 -PERSISTENT_BIN="/data/bin" -RUNNER_PATH="$PERSISTENT_BIN/act_runner" -SYSTEM_LINK="/usr/local/bin/act_runner" - -# 创建必要目录 -mkdir -p /data/runners -mkdir -p "$PERSISTENT_BIN" -mkdir -p /var/log/supervisor -mkdir -p /var/run - -# 创建主 supervisor 配置文件 -cat > /etc/supervisor/supervisord.conf < $RUNNER_PATH" - fi - - # 验证版本 - RUNNER_VERSION=$("$SYSTEM_LINK" --version 2>/dev/null || echo "unknown") - echo " Version: $RUNNER_VERSION" -elif [ -f "$SYSTEM_LINK" ]; then - # 旧版本可能在系统路径,迁移到持久化目录 - echo "⚠ Found act_runner in system path, migrating to persistent storage..." - cp "$SYSTEM_LINK" "$RUNNER_PATH" - chmod +x "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo " ✓ Migrated to: $RUNNER_PATH" -else - # 没有找到 act_runner - echo "⚠ act_runner not installed yet!" - echo "" - echo "Please run the setup script first:" - echo " docker-compose exec gitea-runner /data/setup.sh" - echo "" - echo "This will download and install the Gitea Runner to persistent storage." - echo "Container is waiting..." - - # 等待 act_runner 安装 - while [ ! -f "$RUNNER_PATH" ] && [ ! -f "$SYSTEM_LINK" ]; do - sleep 10 - done - - # 再次检查并创建链接 - if [ -f "$RUNNER_PATH" ]; then - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and linked!" - elif [ -f "$SYSTEM_LINK" ]; then - cp "$SYSTEM_LINK" "$RUNNER_PATH" - ln -sf "$RUNNER_PATH" "$SYSTEM_LINK" - echo "✓ act_runner detected and migrated!" - fi -fi - -# 为每个已注册的 runner 创建 supervisor 配置 -echo "" -echo "Scanning for registered runners..." -RUNNER_COUNT=0 - -if [ -d "/data/runners" ]; then - for runner_dir in /data/runners/*/; do - if [ -d "$runner_dir" ]; then - runner_name=$(basename "$runner_dir") - - if [ -f "$runner_dir/.runner" ] && [ -f "$runner_dir/config.yaml" ]; then - echo "Found runner: $runner_name" - - # 创建该 runner 的 supervisor 配置 - cat > "/etc/supervisor/conf.d/runner-${runner_name}.conf" </dev/null)" ]; then - echo "No runners registered yet." - return - fi - - printf "%-20s %-15s %-30s\n" "Name" "Status" "Log File" - echo "-------------------------------------------" - - for runner_dir in /data/runners/*/; do - if [ -d "$runner_dir" ]; then - runner_name=$(basename "$runner_dir") - - if [ -f "$runner_dir/.runner" ]; then - # 获取状态 - status=$(supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}') - [ -z "$status" ] && status="NOT_LOADED" - - log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - printf "%-20s %-15s %-30s\n" "$runner_name" "$status" "$log_file" - fi - fi - done - echo "" -} - -# 函数:查看 runner 详细信息 -show_runner() { - local runner_name=$1 - local runner_dir="/data/runners/${runner_name}" - - if [ ! -d "$runner_dir" ]; then - echo "✗ Runner '$runner_name' not found!" - return 1 - fi - - echo "Runner Details: $runner_name" - echo "-------------------------------------------" - echo "Directory: $runner_dir" - - if [ -f "$runner_dir/config.yaml" ]; then - echo "" - echo "Configuration:" - cat "$runner_dir/config.yaml" - fi - - echo "" - echo "Status:" - supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}' - echo "" -} - -# 函数:删除 runner -delete_runner() { - local runner_name=$1 - local runner_dir="/data/runners/${runner_name}" - - if [ ! -d "$runner_dir" ]; then - echo "✗ Runner '$runner_name' not found!" - return 1 - fi - - echo "⚠ Warning: This will permanently delete runner '$runner_name'" - read -p "Are you sure? (y/N): " -n 1 -r - echo - - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Deletion cancelled." - return 0 - fi - - echo "Stopping runner..." - supervisorctl stop "runner-${runner_name}" 2>/dev/null || true - - echo "Removing configuration..." - rm -f "/etc/supervisor/conf.d/runner-${runner_name}.conf" - - echo "Deleting runner directory..." - rm -rf "$runner_dir" - - echo "Updating supervisor..." - supervisorctl reread - supervisorctl update - - echo "" - echo "✓ Runner '$runner_name' deleted successfully!" -} - -# 函数:查看 runner 日志 -logs_runner() { - local runner_name=$1 - local lines=${2:-50} - - local log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - if [ ! -f "$log_file" ]; then - echo "✗ Log file not found for runner '$runner_name'" - return 1 - fi - - echo "Showing last $lines lines of '$runner_name' logs:" - echo "-------------------------------------------" - tail -n "$lines" "$log_file" -} - -# 函数:实时查看日志 -follow_logs() { - local runner_name=$1 - local log_file="/var/log/supervisor/runner-${runner_name}.out.log" - - if [ ! -f "$log_file" ]; then - echo "✗ Log file not found for runner '$runner_name'" - return 1 - fi - - echo "Following logs for '$runner_name' (Press Ctrl+C to exit):" - echo "-------------------------------------------" - tail -f "$log_file" -} - -# 函数:启动/停止/重启 runner -control_runner() { - local action=$1 - local runner_name=$2 - - case $action in - start|stop|restart) - echo "${action^}ing runner '$runner_name'..." - supervisorctl "$action" "runner-${runner_name}" - ;; - *) - echo "✗ Invalid action: $action" - return 1 - ;; - esac -} - -# 函数:显示所有 runner 状态 -status_all() { - echo "All Runners Status:" - echo "-------------------------------------------" - supervisorctl status | grep "^runner-" || echo "No runners running." - echo "" -} - -# 主菜单 -show_menu() { - echo "Choose an action:" - echo " 1) List all runners" - echo " 2) Show runner details" - echo " 3) Add new runner" - echo " 4) Delete runner" - echo " 5) Start runner" - echo " 6) Stop runner" - echo " 7) Restart runner" - echo " 8) View runner logs" - echo " 9) Follow runner logs (real-time)" - echo " 10) Show all runners status" - echo " 0) Exit" - echo "" -} - -# 主程序 -if [ $# -eq 0 ]; then - # 交互模式 - while true; do - show_menu - read -p "Enter your choice: " choice - echo "" - - case $choice in - 1) - list_runners - ;; - 2) - read -p "Enter runner name: " runner_name - show_runner "$runner_name" - ;; - 3) - echo "Starting registration process..." - /data/register.sh - ;; - 4) - read -p "Enter runner name to delete: " runner_name - delete_runner "$runner_name" - ;; - 5) - read -p "Enter runner name to start: " runner_name - control_runner start "$runner_name" - ;; - 6) - read -p "Enter runner name to stop: " runner_name - control_runner stop "$runner_name" - ;; - 7) - read -p "Enter runner name to restart: " runner_name - control_runner restart "$runner_name" - ;; - 8) - read -p "Enter runner name: " runner_name - read -p "Number of lines (default 50): " lines - logs_runner "$runner_name" "${lines:-50}" - ;; - 9) - read -p "Enter runner name: " runner_name - follow_logs "$runner_name" - ;; - 10) - status_all - ;; - 0) - echo "Goodbye!" - exit 0 - ;; - *) - echo "Invalid choice!" - ;; - esac - - echo "" - read -p "Press Enter to continue..." - clear - done -else - # 命令行模式 - case $1 in - list|ls) - list_runners - ;; - show|info) - show_runner "$2" - ;; - add|register) - /data/register.sh - ;; - delete|rm|remove) - delete_runner "$2" - ;; - start) - control_runner start "$2" - ;; - stop) - control_runner stop "$2" - ;; - restart) - control_runner restart "$2" - ;; - logs) - logs_runner "$2" "${3:-50}" - ;; - follow) - follow_logs "$2" - ;; - status) - status_all - ;; - *) - echo "Usage: $0 [command] [runner_name]" - echo "" - echo "Commands:" - echo " list - List all runners" - echo " show - Show runner details" - echo " add - Add new runner" - echo " delete - Delete a runner" - echo " start - Start a runner" - echo " stop - Stop a runner" - echo " restart - Restart a runner" - echo " logs [lines] - View runner logs" - echo " follow - Follow runner logs (real-time)" - echo " status - Show all runners status" - echo "" - echo "Or run without arguments for interactive mode." - exit 1 - ;; - esac -fi diff --git a/docker-runner/standard/setup.sh b/docker-runner/standard/setup.sh deleted file mode 100644 index e2180fc..0000000 --- a/docker-runner/standard/setup.sh +++ /dev/null @@ -1,141 +0,0 @@ -#!/bin/bash - -echo "==========================================" -echo " Gitea Runner Installation Script " -echo "==========================================" -echo "" - -# 持久化安装路径 -INSTALL_PATH="/data/bin/act_runner" -SYSTEM_PATH="/usr/local/bin/act_runner" - -# 创建目录 -mkdir -p /data/bin - -# 检查是否已安装 -if [ -f "$INSTALL_PATH" ]; then - CURRENT_VERSION=$($INSTALL_PATH --version 2>/dev/null | grep -oP 'version \K[0-9.]+' || echo "unknown") - echo "⚠ act_runner already installed (version: $CURRENT_VERSION)" - echo " Location: $INSTALL_PATH" - echo "" - read -p "Do you want to reinstall/upgrade? (y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Installation cancelled." - exit 0 - fi - rm -f "$INSTALL_PATH" "$SYSTEM_PATH" -fi - -# 获取要安装的版本 -echo "Available versions: https://dl.gitea.com/act_runner/" -echo "" -read -p "Enter version to install (default: 0.2.13): " RUNNER_VERSION -RUNNER_VERSION=${RUNNER_VERSION:-0.2.13} - -ARCH=$(uname -m) -case "$ARCH" in - x86_64) - RUNNER_ARCH="amd64" - ;; - aarch64|arm64) - RUNNER_ARCH="arm64" - ;; - armv7l) - RUNNER_ARCH="arm-7" - ;; - *) - echo "⚠ Unknown architecture: $ARCH" - RUNNER_ARCH="arm64" - ;; -esac - -# 确认架构 -echo "" -echo "Detected architecture: $ARCH -> $RUNNER_ARCH" -read -p "Is this correct? (Y/n): " -n 1 -r -echo -if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "" - echo "Available architectures:" - echo " 1. amd64 (x86_64)" - echo " 2. arm64 (aarch64)" - echo " 3. arm-7 (armv7l)" - read -p "Select architecture (1-3): " ARCH_CHOICE - case "$ARCH_CHOICE" in - 1) RUNNER_ARCH="amd64" ;; - 2) RUNNER_ARCH="arm64" ;; - 3) RUNNER_ARCH="arm-7" ;; - *) - echo "Invalid choice. Exiting." - exit 1 - ;; - esac -fi - -DOWNLOAD_URL="https://dl.gitea.com/act_runner/${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-${RUNNER_ARCH}" - -echo "" -echo "Download Configuration:" -echo " Version: $RUNNER_VERSION" -echo " Architecture: $RUNNER_ARCH" -echo " URL: $DOWNLOAD_URL" -echo " Install Location: $INSTALL_PATH (persistent)" -echo "" -read -p "Proceed with download? (Y/n): " -n 1 -r -echo -if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "Installation cancelled." - exit 0 -fi - -echo "" -echo "Downloading act_runner..." -echo "" - -# 下载到持久化目录 -if curl -L "$DOWNLOAD_URL" -o "$INSTALL_PATH"; then - chmod +x "$INSTALL_PATH" - - # 同时创建软链接到系统路径 - ln -sf "$INSTALL_PATH" "$SYSTEM_PATH" - - # 验证安装 - if $INSTALL_PATH --version; then - echo "" - echo "==========================================" - echo "✓ act_runner installed successfully!" - echo "==========================================" - echo "" - echo "Version: $($INSTALL_PATH --version)" - echo "Location: $INSTALL_PATH (persistent storage)" - echo "" - echo "Next steps:" - echo "1. Register the runner:" - echo " docker-compose exec gitea-runner /data/register.sh" - echo "" - echo "2. Restart the container:" - echo " docker-compose restart" - echo "" - echo "Note: act_runner is saved in persistent storage" - echo " and will survive container restarts." - echo "" - else - echo "" - echo "✗ Installation verification failed!" - rm -f "$INSTALL_PATH" "$SYSTEM_PATH" - exit 1 - fi -else - echo "" - echo "✗ Download failed!" - echo "Please check:" - echo " - Internet connection" - echo " - Version number is correct: $RUNNER_VERSION" - echo " - Architecture is correct: $RUNNER_ARCH" - echo " - URL is accessible: $DOWNLOAD_URL" - echo "" - echo "You can check available versions at:" - echo " https://dl.gitea.com/act_runner/" - exit 1 -fi