Apple硬件上运行Gitea Actions:从架构适配到生产化配置

Apple硬件上运行Gitea Actions:从架构适配到生产化配置 最近在 Apple 硬件上折腾 Gitea Actions最强烈的感受是Gitea Actions 本身的写法和 GitHub Actions 已经非常接近迁移成本不高但“在 Apple 硬件上跑”这个前提会引入不少额外问题尤其是 Apple Silicon 的 ARM64 架构、Docker Desktop 在 macOS 上的资源限制、act_runner 的注册和运行模式选择。这篇文章就把从零到一的过程拆开讲一遍重点是不让后面的人再踩我已经踩过的坑。如果你正打算在一台 Mac 上用 Gitea 做内网代码托管或者想把 Mac 当作 CI 执行机可以先花几分钟把下面的内容过一遍。文章会按“先判断角色 - 再准备环境 - 跑通最小样例 - 处理架构和资源问题 - 再谈生产化配置”的顺序展开每一步都会给出判断标准。1. 先判断你的使用姿势Mac 是做服务端还是只做 Runner1.1 三种常见角色在实际部署中Apple 硬件在 Gitea Actions 体系里通常有三种角色。第一种角色Gitea 服务端直接跑在 Mac 上。适合个人开发、小团队内网体验仓库、管理界面、Actions 功能都在同一台机器上。第二种角色Gitea 服务端跑在内网服务器Mac 只作为 act_runner 执行任务。适合团队已经把 Gitea 部署在 Linux 服务器上的场景Mac 可以专门跑 iOS、macOS 的构建任务。第三种角色Mac 既跑 Gitea 服务端也跑 act_runner。一台机器完成代码托管和 CI 执行最省服务器但资源瓶颈和稳定性问题会被放大。这三种角色对应的问题完全不同。角色一最省事角色二最接近生产形态角色三适合个人或者任务量很小的场景。我见过不少人把 Mac 当作“内网服务器”来装 Gitea然后又把 Docker、Nginx、构建任务全部压在同一台机器上。短时间看没问题但如果你同时跑多个 Actions 任务CPU、内存、磁盘 IO 都会被拉高Docker Desktop 本身还要占一部分资源。所以第一步不是急着装而是先想清楚这台 Mac 到底承担什么角色。1.2 能启动 Gitea 不等于能顺畅跑 Actions很多教程只会告诉你“安装 Gitea打开仓库启用 Actions”于是你很快能得到一个能正常访问的 Gitea 页面。但第一次提交 workflow 后任务很可能在 runner 注册、label 匹配、镜像拉取、容器执行这四个环节里卡住。原因在于Gitea 服务端和 Actions 执行器是两套东西。Gitea 负责接收仓库的推送事件然后把任务交给已注册的 runner 去执行。runner 没有注册成功、label 对不上、Docker 环境有问题页面上的 workflow 就会一直处于排队或者失败状态。所以“Gitea 能打开”和“Actions 能跑通”是两件事判断标准要分开。我建议的验证顺序是先确认 Gitea 服务端界面正常再确认 runner 在线然后跑一个最简单的 workflow最后再逐步增加构建、测试、发布步骤。不要在还没有确认最小链路的时候就直接套用完整项目的流水线那样报错后很难定位问题。1.3 Apple Silicon 的架构差异这是 Apple 硬件上最容易被忽略的问题。Apple Silicon 芯片是 arm64 架构而很多现成的 CI 镜像默认只有 amd64 版本比如一些老旧的系统镜像、旧版本语言运行环境镜像。你在 Apple Silicon 上拉取这类镜像后直接跑很可能遇到exec format error。这个报错不是脚本写错了而是主机架构和镜像架构不匹配。Docker Desktop 在较新版本里支持通过 Rosetta 模拟 x86_64 镜像但模拟会带来额外开销而且不是所有镜像行为都一致。稳妥的做法是优先选择支持多架构的镜像或者在 workflow 里显式声明平台。比如node:20-alpine这类镜像通常同时提供 amd64 和 arm64而一些比较老的镜像可能只有 amd64。所以判断一个镜像能不能用不能只看名字还要在本地先拉下来跑一次。2. 环境准备Gitea 服务端与 act_runner 的运行模式2.1 Gitea 服务端可以放在哪Gitea 本身是一个很轻量的 Git 服务程序。在 Apple 硬件上你可以直接下载对应平台的二进制文件运行也可以使用 Homebrew 安装。安装后需要准备一个数据目录和一个配置文件Gitea 默认会监听 3000 端口。首次打开页面时界面会引导你完成管理员账号、数据库、站点名称等设置。如果你只是想体验 Actions本地跑一个 Gitea 服务端是成本最低的方式。如果是内网团队使用建议把 Gitea 放到一台可以长时间开机的 Linux 机器上Mac 只负责执行构建任务。因为 Mac 的睡眠、自动更新、重启都会影响 CI 的可用性。很多第一次在 Mac 上搭 Gitea 的人会把 Mac mini 当作服务器长期运行这在业务量不大时可以但最好在系统设置里关闭自动休眠外接电源也不要断开。内网环境下使用 Gitea还有一个经常被提到的点用户 SSH 密钥管理。Gitea 后台可以管理每个用户的 SSH 公钥团队内通过 SSH 协议推送和克隆代码会很方便。你可以在用户设置的“SSH 密钥”页面添加公钥之后使用git你的Gitea地址:用户名/仓库名.git这种地址拉代码。2.2 act_runner 的 Docker 模式Gitea Actions 的任务执行器是 act_runner。act_runner 有两种运行模式Docker 模式和宿主模式。Docker 模式是常见的默认选择。每个 job 在 Docker 容器里执行workflow 里定义的每个步骤都会被封装在容器中环境隔离、可重复性都更好也能复用大量现成的镜像。在 Apple 硬件上使用 Docker 模式意味着这台 Mac 必须能运行 Docker 容器。macOS 上常见的是 Docker Desktop也可以用 colima 这类轻量方案。Docker Desktop 在 macOS 上的特殊性在于它底层是一个 Linux 虚拟机容器实际上跑在虚拟机里不是直接跑在 macOS 上。这带来两个直接影响。第一容器里访问宿主机文件时存在路径映射你可能会看到容器里的路径和 macOS 上的路径不一致。第二资源配额需要在 Docker Desktop 设置里手动调整默认分配的内存和 CPU 往往不够跑重任务。2.3 act_runner 的宿主模式宿主模式不依赖 Dockeract_runner 直接在当前操作系统中执行命令。这种模式对 macOS 原生任务很友好比如 Xcode 构建、Swift Package 编译、签名、公证这些场景在 Docker 容器里反而很别扭因为容器里不一定有完整的 Xcode 工具链签名和证书管理也更麻烦。但宿主模式的隔离性弱。workflow 里的步骤会直接操作用户目录、环境变量、系统工具链一旦脚本写得不干净可能污染开发机环境。我的建议是如果用宿主模式尽量单独准备一台专门跑 CI 的 Mac不要在主力开发机上直接开否则一次误操作可能影响日常开发环境。宿主模式下还有一个容易被忽略的点标签。Gitea 的 workflow 文件里会写runs-on: xxx这个值必须和 runner 注册时的 label 对应上。Docker 模式下一般用ubuntu-latest这类 label宿主模式下可以在注册时自定义一个 label比如macos-arm64。很多第一次使用的人会卡在这一步workflow 里写的是ubuntu-latest但 runner 注册时只填了macos-arm64于是任务永远匹配不到 runner。2.4 两种模式怎么选简单总结涉及 Python、Node、Java 这类通用语言构建用 Docker 模式更稳环境干净、好复现涉及 macOS 特有工具链比如 iOS 打包、Xcode 相关用宿主模式更合适。如果是 Apple Silicon 机器还有一层考虑通用 Linux 镜像通过 Docker 跑速度和架构都可能和本地开发有差异宿主模式直接利用 macOS 的原生工具链性能上更自然。对比项Docker 模式宿主模式环境隔离好弱通用构建方便可复用镜像依赖本机工具链macOS 原生任务困难适合资源开销额外占用 VM 资源直接使用本机资源适合场景前端、后端、测试iOS、macOS 打包3. 在 Apple 硬件上跑通第一个 Actions 任务3.1 创建仓库并启用 Actions假设你已经启动 Gitea 服务端并创建了一个测试仓库。在仓库页面的“设置”里一般可以找到 Actions 相关选项或者通过 Gitea 站点管理员的配置页面启用。不同版本的入口位置可能会变但核心思路一样先确认 Actions 功能没有关闭并且当前用户有权限注册 runner。然后要生成注册令牌。在 Gitea 管理后台的 Actions 相关页面里可以创建一个注册 token。act_runner 注册时需要用到这个 token它是 runner 和服务端建立信任关系的关键。如果 token 过期或复制错了runner 会一直显示离线。这里容易混淆一点Gitea 的 Actions 注册 token 和用户访问令牌、仓库部署密钥不是一回事。Actions token 是给 runner 注册用的不是给 Git 推送用的。我第一次配置时在仓库里找了半天后来才发现要看站点管理后台。如果你在页面里找不到优先去管理员相关的菜单里找。3.2 安装 act_runneract_runner 可以从 Gitea 官方发布页面下载选择对应操作系统的二进制。Apple Silicon 机器选 darwin-arm64Intel Mac 选 darwin-amd64。下载后给二进制文件加上可执行权限放到一个专门目录里。目录要固定因为之后启动 runner 都会从这个目录运行。注册命令大致是./act_runner register --instance http://localhost:3000 --token 你的注册令牌执行后它会询问一些选项比如 runner 的名称和标签。如果只是在 Mac 本机测试可以先用默认标签。如果你希望 workflow 里写runs-on: macos-arm64注册时就要手动填macos-arm64。这个标签决定 workflow 能不能匹配到这个 runner。注册成功后再执行./act_runner daemonrunner 就会开始监听 Gitea 推送过来的任务。正常情况下Gitea 后台会看到这个 runner 处于在线状态。这里要提醒一下daemon 进程会一直占着终端。如果 CtrlC 退出runner 就会离线。你可以在后面用 nohup 或者服务管理工具把 daemon 放到后台运行。3.3 编写首个 workflow 文件在仓库根目录创建.gitea/workflows/demo.yml。注意 Gitea Actions 的默认目录是.gitea/workflows不是.github/workflows。如果你习惯 GitHub Actions这里非常容易写错。一个最小的 workflow 示例name: Demo on: [push] jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkoutv4 - name: Run a script run: echo Hello from Gitea Actions示例里的actions/checkoutv4需要 runner 能访问 GitHub 公共仓库或者本地已经有缓存。在内网环境里这个步骤很可能因为无法访问 GitHub 而失败。这也是一个需要提前判断的点如果你的网络环境无法访问 GitHub就不能直接依赖公共 actions要么在 Gitea 里配置镜像要么把 checkout 换成git clone之类的简单命令。提交并推送这个文件然后在 Gitea 仓库的 Actions 标签页里应该能看到一次新的运行记录。如果你是第一次接触 Gitea Actions建议先不要急着加复杂脚本就把一个 echo 跑通确认链路完整。3.4 验证任务成功与失败判断任务跑起来后第一步看状态如果一直排队说明没有匹配到 runner先查 label 是否一致。如果显示失败进入任务日志看具体是哪一步报错。如果是exec format error优先考虑镜像架构问题。如果是docker: command not found说明 runner 所在环境里找不到 Docker。如果是 checkout 失败先看网络和公共 action 的来源。成功时任务列表里会显示绿色对勾日志里能看到你写的输出文本。第一次跑通不需要追求复杂流程只要链路通了后面再逐步加构建、测试、部署步骤才有意义。注意不要一上来就开最大并发。先用一条简单任务确认输入、输出和日志都正常再考虑批量任务和多仓库并行。4. Apple Silicon 上最容易卡住的几个问题4.1 镜像架构导致的 exec format error这是 Apple Silicon 上最常见的问题。很多 CI 镜像只提供 amd64 版本在 arm64 的 Mac 上用 Docker Desktop 拉取后容器启动时通常会报exec format error。这个报错在 GitHub Actions 的标准 Linux 环境里很少出现所以排查时容易懵。解决方案有三个方向。第一尽量选择 multi-arch 镜像。比如node:20-alpine、python:3.12-slim这类镜像通常同时提供 amd64 和 arm64Docker 会按当前架构自动选择。第二在 workflow 里显式指定平台比如在 Docker 相关命令里加--platformlinux/amd64让容器走模拟层。第三在 Docker Desktop 里开启 Rosetta 模拟支持让部分 amd64 镜像可以直接运行。这三种方式各有代价。方案一最干净方案二和方案三会有性能损耗。而且不是所有二进制工具链都能在模拟层下稳定运行。我建议在写 workflow 之前先在本地手动执行一次docker run验证镜像确认启动、命令执行都正常再写进流水线。4.2 Docker Desktop 的资源和卷挂载问题Docker Desktop 在 macOS 上不是直接跑容器而是通过 Linux 虚拟机。它默认只分配一部分 CPU 和内存。如果你同时开多个构建任务内存耗尽、容器被杀、任务突然失败都比较常见。出现这种情况时先看 Docker Desktop 的资源额度而不是先去改 workflow。另一个问题是卷挂载路径。容器里访问 macOS 文件时路径会经过 Docker Desktop 的映射。你会发现容器里看到的路径和 macOS 上看到的路径不一致。比如 macOS 的/Users/xxx在容器里可能是/host_mnt/Users/xxx或/private/Users/xxx。如果你在 workflow 里把路径写死很容易读到不存在的目录。解决思路是不要在容器里依赖宿主机路径尽量把文件复制到容器内的工作目录如果必须挂载先在容器里执行pwd和ls确认实际路径再做后续操作。日志里如果出现类似no such file or directory不要急着怀疑脚本逻辑先查路径映射。4.3 宿主模式下的权限和路径问题使用宿主模式时act_runner 会以当前用户身份执行脚本。这时候要考虑几个风险。当前用户对工作目录是否有写权限这是最基础的。脚本是否依赖特定的 shell、PATH、环境变量尤其是用户的.zshrc或.bash_profile是否被加载不同系统环境差异很大。多个 job 同时运行时文件目录是否冲突也需要提前设计。最后脚本是否会不经意间改动系统级配置这在自由开放给团队使用时风险更高。我的建议是宿主模式只跑可信仓库的任务。Gitea 的 Actions 本身可以限制哪些仓库能触发任务但如果你把 Gitea 开放给团队所有人宿主模式可能会成为安全隐患。权限和隔离要提前想清楚。如果只是个人使用宿主模式相对方便但也要在 workflow 里尽量用set -e之类的参数让脚本在出错时及时退出。4.4 日志排查顺序遇到任务失败不要只盯着最后几行。推荐按以下顺序排查先看 runner 是否在线。runner 离线时任务会排队根本不会进入执行阶段。再看 label 是否匹配。workflow 的runs-on必须和 runner 的 label 一致。然后看 job 是否创建成功。创建失败通常是 runner 配置问题。接着看具体步骤日志。前几步失败往往与 checkout、镜像拉取、依赖安装有关。最后看环境变量和路径输出确认容器内和宿主机路径差异。这个顺序能帮你把问题从“配置层”一路收敛到“执行层”。很多问题看起来是脚本报错实际是前面的环境没准备好。5. 进阶把 Apple 硬件变成内网 CI 执行机5.1 多 runner 注册与标签管理一台 Mac 上可以注册多个 act_runner也可以在多台 Mac 上各注册一个 runner。Gitea 会根据 label 把任务分派给合适的 runner。标签不能只写一个笼统的名字最好包含关键信息。比如macos-arm64linux-amd64self-hostedxcode这样 workflow 里可以按需选择。比如一个 iOS 打包任务要求跑在macos-arm64上一个通用构建任务要求跑在linux-amd64的 Linux runner 上两者就不冲突。Gitea 的任务队列会根据 label 自动调度。多 runner 之后要考虑任务并发和资源占用。两台 Mac 同时注册如果都接收相同的 labelGitea 会随机分配。这时候要留意每台机器的空闲资源。如果某台机器已经跑了很多任务可以在注册时用不同的 label 区分轻重任务比如macos-arm64-heavy和macos-arm64-lite。5.2 典型内网组合Gitea、Docker、Nginx、私有容器仓库在真实内网环境里Gitea Actions 很少是孤立的。比较常见的组合是Gitea 作为代码托管和 CI/CD 入口。Nginx 做反向代理负责域名、HTTPS 和端口转发。Docker 或容器运行时负责执行构建任务。私有容器仓库用于存放构建产物镜像。构建工具链负责 Spring Boot、Node 等应用的打包部署。很多团队会拿 Gitea 替代 GitHub 或 GitLab 作为内网代码平台再用 Actions 完成类似 Jenkins 的流水线能力。对于一个 Spring Boot 项目常见流程是推送代码 - Actions 触发构建 - Maven 打包 - 构建镜像 - 推送到镜像仓库 - 部署到服务器。在这个链路里Gitea Actions 负责编排执行机负责跑构建镜像仓库负责存储产物Nginx 负责对外暴露。Apple 硬件在这个组合里比较适合做“执行机”或“测试机”不太适合做长期运行的构建服务器。因为 macOS 的电源管理、系统更新、锁屏休眠都会影响任务稳定性。如果团队用的是 Mac mini可以在系统设置里关闭自动休眠但这也只是降低风险不能完全避免。真正要求高可用的时候还是建议准备专门的 Linux 构建机Mac 只跑和 Apple 平台强相关的构建任务。除了 Gitea Actions一些团队也用过 Drone 作为 Gitea 的 CI 方案但 Actions 的好处是 Gitea 原生集成不用额外起一套服务。如果你已经接入了 Docker、Nginx、Harbor 这类基础组件Gitea Actions 可以只作为流水线编排层构建能力由这些底层组件提供。5.3 与 GitHub Actions、GitLab CI、Jenkins 的横向对比Gitea Actions 的核心优势是“轻量 兼容 GitHub Actions 语法”。它的 workflow 和 GitHub Actions 很像迁移成本低。如果你已经在 GitHub Actions 里写过流水线搬到 Gitea Actions 时只需要把目录改成.gitea/workflows再把一些公共 action 来源换成可用镜像或缓存即可。和 GitLab CI 相比Gitea Actions 的配置写法更接近 GitHub 风格Gitea 整体也更轻量。GitLab CI 的功能更厚重适合大团队但对小团队来说维护成本会高一些。如果你已经有 GitLab 基础设施不一定非要迁到 Gitea如果是从零搭建Gitea Actions 会更轻。和 Jenkins 相比Gitea Actions 的配置是声明式的仓库即配置更容易版本化管理。Jenkins 的灵活性和插件生态更好但 Jenkinsfile 和项目配置的管理方式相对更“重”。如果团队本来就在用 Jenkins并且已经积累了大量流水线没必要为了换而换如果是从零搭建Gitea Actions 会是更轻的选择。对比项Gitea ActionsGitHub ActionsGitLab CIJenkins配置文件位置.gitea/workflows.github/workflows.gitlab-ci.ymlJenkinsfile托管成本低适合内网高依赖公共平台中高中高插件生态依赖社区镜像成熟成熟非常丰富适合团队中小型、内网公开项目、云上中大型团队已有 Jenkins 老团队6. 最后一点经验从样例到生产边界在哪里6.1 适合在 Apple 硬件上跑的任务从实际测试的感受看下面这些场景在 Apple 硬件上跑 Gitea Actions 是比较顺畅的。前端构建比如 Node、Vite、Webpack 这类任务用 Docker 模式挑 multi-arch 镜像就能跑。macOS 原生构建比如 Xcode 打包、Swift 编译、签名、公证用宿主模式最合理。文档生成、静态站点部署对资源要求低Mac 完全能胜任。小团队内网测试跑 lint、单元测试、简单的镜像构建不需要高性能服务器Mac 足够。如果你用的是 Apple Silicon而且构建任务主要跑在 Linux 容器里速度和工具链选择都要多留一点余量。同一个项目在 x86_64 Linux 服务器上可能原生编译在 arm64 容器里可能要模拟最终产物也可能有差异。这个问题在“只要能在 CI 里跑通”的场景里不明显在“必须产出和线上一致产物”的场景里就很关键。6.2 不适合硬跑的任务不太建议在 Apple 硬件上硬跑的任务包括长时间高并发的重型构建。比如几十个并行任务同时处理大型项目Mac 的散热、内存和磁盘会成为瓶颈Docker Desktop 的 Linux 虚拟机也扛不住太多容器同时运行。强依赖 x86_64 环境的生产镜像构建。在 Apple Silicon 上可以用模拟但性能和一致性问题会浪费很多时间。需要 7x24 小时稳定执行的服务型任务。Mac 不是为无限连续运行设计的电源、系统更新和硬件老化都要考虑。另外如果你的团队有专门的 Linux 构建服务器就不要把任务强行放到 Mac 上跑。Apple 硬件最大的价值是跑 Apple 平台相关的构建和测试把这一点用足就够了。6.3 最值得先做的事如果你现在准备在 Apple 硬件上搭建 Gitea Actions我会建议按这个顺序来。第一先用一台 Mac 跑通最小链路Gitea 服务端、runner、简单 workflow。第二确认你的常用镜像在 arm64 上能不能正常工作提前排除架构问题。第三再决定用 Docker 模式还是宿主模式。第四能跑通第一个实际项目后再考虑多 runner、标签、Nginx、私有仓库这些生产化配置。第五最后把日志、输出目录、任务队列整理清楚避免任务多了以后互相踩踏。踩过几次坑之后我发现很多问题不是 Gitea Actions 本身能力不够而是前置环境和输入材料没有处理干净。把架构、标签、路径、资源配额这四件事理顺在 Apple 硬件上跑 Gitea Actions 完全可以做到又稳又顺。个人体验下来最值得先做的永远是先把最小样例跑到成功后面再逐步叠加需求会比一上来直接套完整流水线高效很多。