十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

群晖NAS上用Docker部署Gitea:轻量自托管Git服务完全指南

群晖NAS上用Docker部署Gitea:轻量自托管Git服务完全指南 玩自托管这几年我断断续续在好几台设备上折腾过代码仓库。GitLab 太重Gitea 官方 Docker 镜像又轻又稳配合 Synology 的 Docker 套件十几分钟就能把私人 Git 服务跑起来。这篇就把我从零开始的操作过程、踩过的坑、以及后续运维经常要用到的细节一并写出来给想在 NAS 上搭代码仓库的朋友做个参考。整个过程不复杂只要跟着步骤走基本不会卡壳。1. 方案选型为什么是 Gitea 加 Docker1.1 Gitea 到底解决了什么问题个人开发者、小团队或者极客玩家对代码托管的需求其实很明确要有 Git 的完整功能要能管理多个仓库和用户权限要能看提交记录和 Issue最好还带一个简单的 Wiki。Gitea 就是用 Go 写的这么一套轻量级 Git 服务单体二进制文件就能跑资源占用比 GitLab 低一个量级。我自己实测过同样的 NAS 设备GitLab 的容器跑起来内存经常飙到 2GB 以上Gitea 加上配套的数据库内存占用通常能控制在 300MB 到 500MB 之间。对于 Synology 这种内存本来就不宽裕的 NAS 来说这个差距是决定性的。而且 Gitea 的界面非常接近 GitHub 的操作逻辑从 GitHub 迁过来的人几乎不需要学习成本创建仓库、发起 Pull Request、管理 Issue 这些东西都是一眼就能找到的。再往深一层说自托管 Git 服务的核心价值不只是“代码放在自己手里”更在于它可以和现有工作流无缝集成。Gitea 支持 Webhook可以勾连 CI/CD 工具支持 Git LFS可以管理大文件支持镜像仓库功能可以把 GitHub 上的公开仓库定时同步一份到本地作为代码资产备份。这些能力对于一个小团队或者个人开发者来说足够覆盖绝大部分日常场景。1.2 为什么用 Docker 而不是套件中心Synology 套件中心确实有 Git 相关的套件但功能普遍比较基础而且版本更新往往滞后。Gitea 的迭代速度很快安全补丁和功能更新频繁如果用套件方式安装等官方推送新版本可能要很久也缺少灵活的配置项。Docker 方案最大的优势就是环境隔离和可移植性。Gitea 运行在容器里依赖的运行时环境、配置文件、数据目录全部由镜像统一管理不会污染 NAS 本体的系统。以后想升级直接拉新镜像重建容器就行想迁移到别的机器把数据目录打包带走到新机器重新跑一个容器挂载同样的目录数据立刻恢复。另外Docker 的端口映射非常灵活。Synology 的 80 端口通常被 Web Station 占用22 端口被系统 SSH 占用如果你直接在 NAS 上装 Gitea很可能遇到端口冲突。但通过 Docker 的端口映射可以把容器内部的 3000 端口映射到宿主机任意一个空闲端口比如 3000 或者 8888SSH 端口也可以从 22 映射成 2222。这种“容器内不动宿主机随意映射”的机制让部署变得极其干净。1.3 我在方案选择上的几个取舍部署之前有几个方向性的问题需要先想清楚。第一个是数据库的选择Gitea 支持 SQLite、MySQL、PostgreSQL。个人使用或者几个人的小团队直接用 SQLite 最省事一个文件就把所有数据存了备份就是复制文件。用户量上来或者有高并发需求再换 PostgreSQL 也不迟Gitea 官方后台有数据迁移工具虽然不能自动化迁移但操作流程是有文档支撑的。第二个是是否配置 SSH 访问。Gitea 的 HTTP 克隆地址也能用但 SSH 方式免密推送更方便特别是对于经常提交代码的人来说每次输密码非常影响效率。Gitea 容器支持开启内置 SSH 服务只需要把宿主机的某个端口映射到容器内的 22 端口即可。第三个是反向代理要不要配。如果只是局域网内访问NAS 的 IP 加端口号直接用就行如果想通过域名访问域名解析到 NAS 的 IP再把 80/443 端口的请求反代到 Gitea 容器的 3000 端口。Synology 自带的反向代理功能就可以搞定不需要额外装 Nginx。2. 部署前的准备版本要求与关键概念2.1 硬件与系统版本的最低门槛理论上只要是能装 Docker 套件的 Synology 机型都可以跑 Gitea。DSM 6.2 以上版本都内置了 Docker 套件DSM 7.0 之后 Docker 改名为 Container Manager功能上区别不大。我这里以 DSM 7 的 Container Manager 为例做说明DSM 6 的操作路径基本一致只是套件名字叫 Docker。硬件方面Gitea 的官方镜像对 CPU 的要求不高x86 架构的主流型号都没问题。如果你用的是 ARM 架构的机型比如老款的 DS218play 或者部分 J 系列拉镜像时需要留意选择对应 ARM64 的版本标签。Gitea 官方镜像默认支持多架构直接拉取时会自动匹配但如果手动指定了 amd64 的标签在 ARM 机器上是跑不起来的。另外建议内存至少 1GB 以上。我最初在一台 512MB 内存的老 NAS 上试过Gitea 本身能启动但一旦同时跑数据库和其他容器系统就会变得非常卡顿Git 操作也会出现明显延迟。加内存到 2GB 后整个体验才算是可用的状态。2.2 Docker 的几个核心概念怎么理解不管你是在 Synology 上还是在其他平台上用 Docker有几个概念必须弄清楚否则配置的时候容易一头雾水。镜像可以理解成一个只读的模板里面包含了应用运行所需的代码、运行时、依赖库和默认配置。容器是镜像运行起来后的实例可以启动、停止、删除容器内的文件系统是可写的但容器删除后这些改动就没了。卷则是把容器内的某个目录映射到宿主机的一个目录这样即使容器被删掉重建数据依然保存在宿主机上不会丢失。端口映射解决的是“容器外面怎么访问容器里面”的问题。Gitea 容器内部监听 3000 端口宿主机通过某个端口把请求转发到容器的 3000 端口比如访问http://NAS的IP:3000就能打开 Gitea 界面。SSH 同理把宿主机的 2222 端口映射到容器内的 22 端口用户就可以用ssh://gitNAS的IP:2222/用户名/仓库名.git来克隆和推送代码。docker run命令是把镜像启动为容器并配置各种参数的入口在 Synology 的图形界面里这些参数被拆分成各个选项卡和表单。理解了底层命令的逻辑图形界面里的每一项配置就能对号入座了。2.3 网络模式与端口规划怎么做Container Manager 新建容器时网络设置里有 bridge 和 host 两种常见模式。bridge 模式是默认推荐的方式容器有自己的虚拟 IP宿主机通过端口映射把流量转发进去。host 模式直接让容器共享宿主机的网络栈不需要端口映射但会直接占用宿主机端口灵活性差一些。Gitea 用 bridge 模式就足够了。端口规划上我建议 Web 端口和 SSH 端口各占一个。Web 端口选一个不容易被其他服务占用的端口比如 3000 或者 8888。SSH 端口建议选 2222避免和宿主机本身的 22 端口冲突。这里有一个常见的坑如果你把容器 SSH 端口映射到 22而 NAS 的系统 SSH 也监听在 22两者会冲突导致其中一个起不来。所以要么改系统 SSH 端口要么容器 SSH 就用 2222后者显然更省事。另外提一下如果你要使用 Webhook 或者通过公网访问 Gitea最好提前规划好“外部访问地址”。这个地址会写入 Gitea 的配置文件直接影响克隆 URL 的生成。如果规划不当后面再改会比较麻烦不过这个问题我们在第 3 章的首次配置部分会详细展开。3. 完整部署过程逐步演示3.1 第一步在 File Station 里建好目录结构正式拉镜像之前先要规划好数据存放的目录。我习惯在 Docker 的共享文件夹下按应用名建子目录这样所有容器数据都能集中管理备份时一目了然。在 File Station 里进入docker共享文件夹新建gitea文件夹再在gitea下分别建data和config两个子文件夹。data用于存放 Git 仓库数据、数据库文件和上传的附件config用于存放 Gitea 的配置文件。这两个目录后面要挂载到容器内。注意如果你打算以后用容器跑备份或者恢复目录结构一定要从一开始就规划好避免后面迁移时路径混乱。我的习惯是/docker/gitea/data和/docker/gitea/config在任何机器上看到这个路径就知道是干什么的。3.2 第二步拉取 Gitea 镜像打开 Container Manager进入“注册表”或“镜像”页面搜索gitea/gitea。官方镜像名称就是gitea/gitea别搜成别的否则可能拉到第三方打包的镜像配置路径和数据目录有差异出了问题不容易排查。标签选择上如果你对稳定性要求高选latest即可Gitea 的 latest 指向的是当前稳定版本。如果你需要长期固定版本可以选带版本号的标签比如1.22.1之类的具体版本。我个人倾向于用带版本号的标签这样容器重建时可以确保版本完全一致等确认新版本没问题再手动升级。点击下载后等待镜像拉取完成。镜像大小一般在 100MB 左右具体取决于网络环境通常一两分钟就能拉完。3.3 第三步创建容器并配置核心参数镜像拉取完成后点击“运行”或“创建容器”进入配置界面。这里有几个关键配置项需要仔细设置。容器名称随意比如gitea方便辨认即可。勾选“启用资源限制”的话可以给容器设定内存上限防止 Gitea 异常时拖垮 NAS 系统我一般设置 1024MB 上限。端口映射部分“本地端口”填写你希望外部访问的端口容器端口固定为 3000Web和 22SSH。假设我规划 Web 用 3000SSH 用 2222那么映射关系就是3000 - 3000和2222 - 22。存储空间映射部分把本地的docker/gitea/data映射到容器内的/data把docker/gitea/config映射到容器内的/data/gitea/conf。注意这里有个细节Gitea 官方镜像只声明了一个数据卷/data所有配置、仓库、数据库都会存放在/data下的子目录中。如果你像我一样单独挂载了/data/gitea/conf配置文件会单独存放在宿主机目录里方便直接编辑。如果不单独挂载配置文件会嵌套在/data目录下docker/gitea/data里面会自然生成gitea/conf结构。两种方式都可以但挂载方式更有利于直接修改配置。环境变量部分首次部署可以先不用设置太多后面配置向导会引导你填写。如果希望跳过向导直接完成配置可以设置GITEA__server__ROOT_URL、GITEA__server__SSH_PORT等参数但新手不建议这样做首次配置还是可视化操作更直观。配置完成后点击“应用”或“创建”容器会自动启动。3.4 第四步浏览器打开安装向导完成初始化容器启动后在浏览器访问http://NAS的IP:3000就能看到 Gitea 的安装页面。这里有几个配置项需要注意。数据库类型如果是个人使用选择 SQLite如果有一定的并发或者需要集中管理多个实例选择 PostgreSQL 或 MySQL需要提前准备好数据库容器。我个人的选择是 SQLite前期部署最简单数据备份直接复制文件就行实际体验中即使同时有几十个用户操作也没有明显瓶颈只有在仓库数量特别大、并发操作特别多的情况下SQLite 才会成为瓶颈这种情况在个人使用中很少见。站点名称随便填“仓库根目录”保持默认值即可不要随意改动因为这是容器内的路径不是宿主机路径。SSH 服务器端口填2222这里要和你设置的主机映射端口保持一致因为 Gitea 会根据这个端口生成 SSH 克隆地址。还有一个关键的配置项是“Gitea 基础 URL”这里要填用户访问 Gitea 时使用的完整地址比如http://NAS的IP:3000或者你绑定的域名。这个地址会被记录到配置文件中影响 Web 克隆地址的生成。如果填错了克隆地址就会变成内网 IP 或者 localhost别人拿过去根本用不了。管理员账号设置部分建议勾选“立即创建管理员账号”设置好管理员用户名、邮箱和密码。如果跳过这一步后续第一个注册的用户会自动成为管理员存在潜在风险。点击安装后Gitea 会初始化数据库几秒钟后自动跳转到登录页面。到这里一个基础的 Gitea 服务就算跑起来了。3.5 第五步验证 SSH 克隆与推送是否正常Web 界面创建好一个测试仓库后首要事情就是验证 SSH 访问是否正常。在用户设置里找到“SSH 密钥”页面添加你本机的公钥然后在仓库页面复制 SSH 克隆地址正常情况应该长这样ssh://git192.168.1.100:2222/用户名/仓库名.git。然后在本机执行git clone这个地址如果能够成功拉取代码说明 SSH 配置链路完全正常。如果提示ssh: connect to host ... port 2222: Connection refused多半是端口映射没生效回到容器设置里检查端口映射。如果提示Permission denied (publickey)要么公钥没加进去要么 Gitea 的 SSH 服务没有正确读取公钥数据。Gitea 用户管理 SSH 公钥的逻辑是公钥数据存在数据库里当 SSH 请求进来时Gitea 内置的 SSH 服务会从数据库里查找匹配的密钥。所以如果你是直连容器内 22 端口的 SSH 方式必须保证容器里的用户目录和数据库是关联的这个关联关系在官方镜像中已经处理好只要按照默认路径映射/data卷就不会有问题。3.6 其他值得做的优化配置基础服务跑起来后我还会顺手做几件事让整个系统更稳定、更好用。第一件事是在 Container Manager 里开启“自动重启”这样 NAS 重启或者 Docker 服务重启后Gitea 容器会自动恢复运行不用手动再去启动。这个选项通常在创建容器时的“高级设置”里也可以在容器创建后通过“编辑”入口修改。第二件事是选择合适的镜像更新策略。我建议不要设置自动拉取最新镜像因为 Gitea 一个版本升级后数据库自动迁移通常是不可逆的万一新版本有问题回滚会比较麻烦。我通常在确认某个新版本发布后先在测试环境里跑几天确认没问题再手动升级生产环境的镜像。第三件事是配置定时备份。我们放在第 5 章具体说明这里先提一个核心思路只要/docker/gitea目录有完整备份整个 Gitea 服务就能随时重建因为代码仓库、数据库、配置文件、用户上传的附件全部在这个目录里。4. 常见问题与排查技巧实录4.1 容器端口冲突怎么办这是我最常遇到的问题。Synology 原生服务占用的端口比较多比如 5000/5001 是 DSM 管理界面80 是 Web Station443 是 HTTPS22 是系统 SSH。如果你规划的端口和这些冲突容器会启动失败Container Manager 里会直接报“端口已被占用”的错误。解决思路很简单换一个没有被占用的端口。但在换端口之前可以在 Container Manager 的“网络”或者终端里执行netstat -tlnp查看端口占用情况判断真正冲突的端口是哪个。有些服务监听的是 0.0.0.0所有网络接口有些只监听某个具体 IP情况不同处理方式也不一样。如果某个端口被系统关键服务占用又实在想用这个端口可以改系统服务的监听端口但这样操作风险较高不推荐新手尝试。我个人的经验是Web 用 3000SSH 用 2222这两个端口在大多数 NAS 上都是空闲的基本不会冲突。4.2 Docker Desktop 启动失败和 NAS 部署有什么关系不少人在 Windows 上折腾过 Docker Desktop也踩过Docker Desktop failed to start because virtualization support wasnt detected这类报错。这个报错的意思是宿主机没有开启硬件虚拟化支持或者 WSL2 所需的虚拟化平台没有启用。这里顺便说清楚一个区别在 Synology NAS 上跑 Docker不依赖 Windows 的虚拟化支持因为 NAS 本身就是 Linux 系统而在 Windows 上跑 Docker Desktop需要在 BIOS/UEFI 里开启 VT-x/AMD-V并且要启用 Windows 的 Hyper-V 或 WSL2 功能。如果你是在 NAS 上部署 Gitea遇到启动问题不太可能是虚拟化导致的更多的还是端口、目录映射或者镜像架构的问题。如果是在 Windows 本地想跑 Docker 环境做开发测试再检查 BIOS 虚拟化开关和 Windows 功能选项。4.3 Gitea 的 SSH 配置了但连不上这个问题的排查优先级我一般按下面的顺序来第一确认端口映射是否正确。进入 Container Manager 的容器设置页面查看端口映射一栏确认宿主机端口是否指向容器内的 22 端口。第二确认 Gitea 配置中的 SSH 端口是否和映射的宿主机端口一致。进入站点管理后台查看“SSH 服务器端口”字段如果填的是 2222那么 SSH 克隆地址里显示的端口也是 2222必须和实际映射端口一致。第三确认用户公钥是否添加成功。第四确认容器日志中有没有报错。一个容易被忽略的细节是Gitea 的 SSH 克隆地址需要基于ROOT_URL和SSH_PORT两个配置来生成。如果在安装向导里填写的“基础 URL”是http://NAS的IP:3000SSH 端口填的是 2222那么克隆地址会正确显示为ssh://gitNAS的IP:2222/...。如果基础 URL 填的是 localhost那克隆地址就会变成ssh://gitlocalhost:2222/...拿这个地址在别的机器上克隆当然连不上。4.4 密码不对、权限错误这类登录问题Gitea 的密码策略和系统账号体系是独立的。你在 DSM 里创建的账号不能直接用来登录 Gitea。Gitea 的用户体系由它自己的数据库管理和 NAS 系统账号没有任何关系。所以如果你在 Gitea 里提示密码不对基本就是账号密码确实不对或者你试图用 DSM 的账号密码登录 Gitea。解决方式是使用浏览器开发者工具或 Gitea 后台管理功能来重置密码。如果你有系统管理员权限可以在 Gitea 的后台“用户管理”页面找到该用户编辑并重新设置密码。如果管理员账号都无法登录可以通过数据库手动更新管理员密码的哈希值但这种方式比较繁琐更简单的方式是直接修改 Gitea 配置文件临时允许外部注册注册一个新管理员后再关闭开放注册。另外提醒一句Gitea 有登录失败次数限制多次输错密码后该 IP 可能会被临时锁定一段时间所以排查问题的时候不要疯狂试密码。4.5 容器迁移和备份恢复的注意点Gitea 容器的迁移其实非常友好因为整个应用的状态都保存在/data目录里。迁移的步骤就是老 NAS 上停掉容器把/docker/gitea目录完整打包新 NAS 上建好同样的目录结构把包解压进去然后创建容器挂载同样的目录设置同样的端口映射。启动后直接访问所有的仓库、用户、配置都还在。这里有一个必须注意的细节如果新 NAS 的 IP 变了SSH 克隆地址里面的 IP 自然也会变但 Gitea 内部记录的仓库路径和 Clone URL 是基于app.ini中配置的ROOT_URL生成的所以迁移后需要登录后台把站点基础 URL 和 SSH 端口修改成新环境的值。Git 客户端本地已有的仓库 remote 地址也需要重新设置git remote set-url origin 新地址。备份频率上我自己的策略是每天凌晨做一次增量备份每周做一次全量备份。同步工具用了 Hyper Backup直接把/docker/gitea目录作为备份源备份目的地是另一台 NAS 或者外置硬盘。因为你还要考虑到仓库数据可能比较大如果备份目标设备的空间有限就要规划好保留策略。5. 进阶玩法与日常运维心得5.1 用群晖反向代理绑定域名如果你想通过域名方式访问 Gitea而不是每次都用 IP 加端口可以用 Synology 自带的反向代理功能。进入“控制面板”-“登录门户”-“高级”-“反向代理”新增一条规则来源协议选择 HTTPS来源主机名填写你的域名来源端口填 443目的地协议选 HTTP目的地主机名填 localhost 或 NAS 的 IP目的地端口填 3000。配置完成后还需要在 Gitea 后台把“基础 URL”修改为https://你的域名这样克隆地址会自动变成这个域名。如果你在 DSM 上已经申请并配置了证书反向代理会自动处理 HTTPS 加密。有一点要特别说明反向代理生效后原来的http://NAS的IP:3000依然可以访问Gitea 的用户名密码登录信息是存储在 Cookie 里的同一个浏览器同时用两个地址访问可能会造成登录态互相干扰有条件的话就统一用一个入口地址。5.2 开启仓库镜像与外部备份Gitea 自带了仓库镜像功能可以从外部 Git 服务同步仓库。在用户设置或系统管理后台可以添加“镜像仓库”填上源仓库的 HTTPS 或 SSH 地址Gitea 会定期拉取更新。这个功能非常适合做 GitHub 仓库的本地备份尤其是那些自己参与维护的开源项目。镜像同步默认是定时执行的间隔时间最小单位是半小时。如果你希望一个仓库的高频备份也可以用 Webhook 的方式在 GitHub 端配置推送事件Gitea 端接收后自动拉取。不过这种方式配置复杂一些大多数人用定时镜像就足够。还有一点是关于 Gitea 的 LFS 功能如果你用 Git LFS 存储大文件LFS 文件默认也存放在/data下的lfs目录备份时一并带上就行。这点容易遗漏因为如果只备份了仓库但没备份 LFS 目录大文件会丢失。5.3 版本升级的稳妥路径Gitea 的版本升级不算复杂但有几件事必须提前做。第一步是备份数据和配置确保万一出问题可以快速回滚。第二步是在 Container Manager 里拉取新版本镜像比如从1.22.1升级到1.23.0。第三步是停止旧容器注意不要删除因为删除是物理移除虽然数据在挂载卷里不会丢但容器配置和网络设定会丢。第四步是用新镜像重新创建容器端口映射和数据卷挂载参照旧容器的设置。第五步是启动新容器观察日志确认启动正常然后访问 Web 界面跑一遍核心功能。Gitea 在启动新版时会自动执行数据库迁移迁移通常是一次性的并且会在日志里记录迁移过程。如果在迁移过程中报错最理智的做法是立刻停掉容器恢复备份然后仔细看日志分析原因。我自己遇到过一次数据库迁移卡在某个表上的情况原因是数据库版本太旧跨了太多主版本后来是分步升级才解决的。所以如果长时间没有升级尽量不要跨越多个大版本直接升到最新。5.4 我自己的一些后续扩展思路Gitea 跑稳定之后我还会在 NAS 上搭配一些其他服务让整个开发环境更完整。比如配合 Drone 或 Woodpecker CI 做自动化构建提交代码后自动跑测试和构建配合本地 Docker Registry 做镜像私服方便推送和拉取内部镜像Gitea 的 Webhook 配置也很灵活可以联动群晖的 Chat 套件或者其他消息通知服务仓库有提交、有 Issue 更新就推送通知到手机。这些扩展本质上都是围绕 Gitea 的 Webhook、API 和容器化特性来做的不用一次性全上按需添加就行。比如你的团队突然需要 CI/CD那就先加一个 Woodpecker CI 容器再把 Gitea 的 OAuth 应用配置好用户就可以直接用 Gitea 账号登录 CI 系统了。迁移和扩展的过程我自己体会下来还是那句老话只要数据卷在容器随时可以重建数据永远丢不了。这也是我在 NAS 上跑任何自托管服务时最看重的一点。
返回列表