资讯动态

用Docker自建GitLab服务器:从部署到调优的完整实践

发布时间:2026/10/14 15:26:08 来源:尧图企业网站定制
先说一个很多人都会踩的坑Spring Boot项目写完了本地跑得挺好一到多人协作、频繁发版的阶段就手忙脚乱。今天张三改了接口没通知你明天李四往仓库里推了个跑不起来的代码整个团队的时间全耗在“谁的环境又坏了”这个问题上。这时候你心里很清楚该上CI/CD了。在众多方案里GitLab自托管服务器是很多团队的首选而这套体系的第一步就是把GitLab服务器本身给搭起来。这篇文章我会把这步拆开揉碎从服务器规划、安装部署到初始化配置和问题排查完整带你走一遍。搭建GitLab服务器这件事本身并不复杂真正的复杂度集中在几个容易被忽略的决策点上选什么安装方式、内存怎么规划、挂在哪个目录、初始密码去哪找、502了怎么办。这些坑我基本都踩过一遍下面会把每个环节为什么这么做、命令参数什么意思、出了问题怎么定位一并讲清楚。无论你现在用的是云服务器还是公司内部机房的一台机器这套流程都能直接照着搬。1. 为什么自建GitLab而不是直接用代码托管平台1.1 自建解决的核心问题很多团队的第一反应是GitHub私有仓库、码云或者其他托管平台不是挺方便的吗为什么还要自己折腾一台服务器答案通常不是功能问题而是下面这几个现实需求第一个是代码安全与合规要求。有些公司对代码资产有硬性要求源码不能出内网只能放在团队能完全控制的服务器上。托管平台再方便数据也终究在别人那里。自建GitLab仓库、备份、权限体系全部在自己手里这一点是刚需。第二个是CI/CD深度绑定。GitLab的卖点从来不只是代码托管而是把代码托管、Merge Request评审、Issue管理、CI/CD流水线全部放在同一个平台里。你用GitLab Runner跑流水线跑完的结果直接显示在Merge Request页面里开发、测试、构建、部署状态一目了然。团队的整个研发流程都能围绕一个平台转起来不需要在多个系统之间来回切换。第三个是成本可控。托管平台的私有仓库和并发构建数是要按档位付费的团队规模一大账单涨得很快。自建GitLab机器是一次性投入后续主要成本就是维护和电费长期算下来在内部项目数量多的情况下往往更划算。当然自建也有代价你要自己管备份、升级、安全补丁、性能调优。所以如果你的团队只有两三个人、项目也完全不敏感直接用一个现成的托管平台反而更省事。但如果你已经确定了要走自建这条路那下面这些内容就是为你准备的。1.2 GitLab在CI/CD链条中的生态优势GitLab的CI/CD为什么值得你为它专门搭一台服务器我举一个实际场景一个Spring Boot项目你希望在开发者推送代码到某个分支后自动触发一系列任务拉取代码、执行单元测试、跑静态检查、构建镜像、推送到镜像仓库、调用远程服务器执行部署。整个过程如果全靠人肉去敲命令一次发布至少浪费十几分钟还容易敲错。用了GitLab CI/CD这些任务被描述在一个.gitlab-ci.yml文件里GitLab服务器负责调度和管理Runner负责执行任何一次提交的状态都能被完整记录下来。而且GitLab的CI/CD是内置在代码平台里的不需要额外维护一套独立的CI系统。这对于中小团队来说学习成本和运维成本都低很多。你只需要在一台机器上装好GitLab后续的Runner、流水线、制品管理、环境管理全都围绕它展开。所以搭建GitLab服务器这件事不是一个孤立的安装任务而是整个持续集成体系的地基。地基打得不好后面所有环节都会跟着难受。这也是我为什么要把这篇文章的重点放在规划和部署细节上。2. 搭建前的服务器规划与环境准备2.1 硬件配置建议先说一个很多人问过的问题GitLab服务器到底需要多大内存官方给出的建议是最低4GB但我测试下来4GB跑GitLab能启动内存会非常紧张。你想想GitLab本质上是一个多组件系统里面有PostgreSQL数据库、Redis缓存、Nginx反向代理、Gitaly存储服务、Sidekiq后台任务再加上Puma Web服务这些都是实实在在吃内存的进程。实际运行起来整体占用很容易突破3GB如果机器同时还跑着其他东西系统很容易触发OOM。我的建议很直接团队规模在20人以内、仓库数量和并发操作都不高的话4核8GB是一个比较舒服的配置。如果你预算有限至少也得保证4GB内存同时配置一个足够大的Swap分区来兜底避免内存一紧张进程被直接杀掉。硬盘方面GitLab的数据体积增长其实比很多人想象得快尤其是带Docker镜像构建和长期制品保留的场景。系统盘和数据盘最好是分开的数据盘单独挂载给GitLab的存储目录这样将来扩容迁移都方便。带宽同样值得注意。如果团队成员分布在不同的城市通过公网访问GitLab那么服务器的上行带宽决定了clone和push的体验。常规的代码操作还好但拉取大仓库、频繁推送构建产物时上行带宽不够会让人非常崩溃。云服务器选型时这块要提前留出余量。2.2 操作系统与基础依赖操作系统方面GitLab官方支持Ubuntu、Debian、CentOS、Rocky Linux等主流发行版。我自己在Ubuntu 20.04和22.04上都跑过稳定性没有问题。CentOS系列在GitLab 16.x之后的官方支持力度有所变化如果没有特殊原因Ubuntu LTS版本是最省心的选择。需要提前安装的基础软件不多但有一项是必须的Docker。虽然GitLab也提供原生的安装包方式但我在比较了两种方式之后更推荐用Docker容器来跑GitLab服务器。原因后面细说先记录一下Docker安装命令。# 安装依赖 sudo apt update sudo apt install -y curl ca-certificates # 添加Docker官方GPG密钥和软件源 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 将当前用户加入docker组避免每次sudo sudo usermod -aG docker $USER # 设置Docker开机自启 sudo systemctl enable docker sudo systemctl start docker装完Docker之后可以顺手验证一下执行docker version能够正常输出版本信息就说明环境这关过了。2.3 安装方式选型Docker还是原生包关于安装方式我见过不少团队用GitLab官方提供的Omnibus安装包直接装在宿主机上。这种方式的好处是运维习惯和普通系统服务一致开机自启、日志查看都可以通过systemctl管理。但它也有明显的短板升级迁移时灵活性差系统环境一旦被搞乱排查起来特别麻烦。相比之下用Docker方式部署GitLab的好处我在实际项目里感受非常明显第一是环境隔离。GitLab依赖的那一套数据库、Redis、Nginx全部封装在容器里不会污染宿主机系统。你不用担心装GitLab时把系统自带的PostgreSQL或Redis版本顶掉。第二是升级回滚方便。官方镜像的版本标签控制得很清晰想升级就换一个tag重新启动容器万一升级出问题把镜像标签切回原来的版本数据目录不变就能快速回滚。这对生产环境的稳定性保障非常重要。第三是备份恢复非常灵活。GitLab的备份机制你已经用上了配合Docker的目录挂载整个容器的数据都会落在宿主机的一个目录下复制这个目录到新机器重新启动容器即可完成迁移。当然Docker方式也有需要注意的地方容器内的路径和宿主机路径的对应关系要提前规划清楚挂载目录一旦启动之后就不要随意改动否则数据会“找不到”。另外容器日志会跟随容器本身日志轮转的配置也需要手动处理一下后面我会讲到。3. Docker方式搭建GitLab服务器实操3.1 挂载目录规划在启动GitLab容器之前先要规划好三个关键目录的映射关系。这一步骤看着不起眼但很多部署事故都出在这里。GitLab容器内有几个核心路径/etc/gitlab存放GitLab的配置文件主要是gitlab.rb所有对GitLab实例的设置都在这里修改。/var/opt/gitlabGitLab的应用数据目录包括仓库数据、数据库文件、上传的附件等。/var/log/gitlab各类组件的日志文件。你需要把这三个目录分别挂载到宿主机的持久化目录。我习惯在宿主机的一个独立目录下统一管理比如sudo mkdir -p /srv/gitlab/config sudo mkdir -p /srv/gitlab/data sudo mkdir -p /srv/gitlab/logs为什么强调单独挂数据目录因为GitLab镜像本身是临时的容器删了重建都没关系但数据目录里的东西是绝对不能丢的。把数据目录拆出来挂在独立磁盘或云盘上磁盘报警、扩容、迁移的时候你只需要动数据目录不需要碰容器。3.2 启动GitLab容器环境准备好之后直接用docker run启动GitLab容器。这里以GitLab 16.x版本为例sudo docker run --detach \ --hostname gitlab.example.com \ --publish 443:443 --publish 80:80 --publish 22:22 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ --shm-size 2g \ gitlab/gitlab-ce:16.10.2-ce.0逐项解释一下关键参数你以后排查问题也用得上--hostname gitlab.example.com这里的hostname需要格外注意。GitLab会把容器内部所有URL都基于这个hostname来生成包括你在网页端看到的项目地址、clone地址、Webhook回调地址。如果你的GitLab是通过IP访问的比如http://192.168.1.100那么这里就要填IP或者你计划使用的域名。等容器启动后再改hostname会牵涉到数据中记录的URL变更比较麻烦。--publish 80:80和--publish 443:443是把容器的HTTP和HTTPS端口映射到宿主机。--publish 22:22是SSH端口这个端口要小心如果宿主机本身的SSH已经用了22这里会冲突。我的建议是如果宿主机就是这台服务器本身且你需要通过SSH远程管理它就给GitLab的SSH映射一个其他端口比如--publish 2222:22然后项目地址里的SSH端口通过配置设置成2222。如果你只是在局域网内用GitLab而且服务器本机的SSH不是22那直接映射22也行。--shm-size 2g这个参数是给容器内的共享内存目录分配空间。GitLab在运行大规模操作时会写一些临时文件到/dev/shm默认Docker只给64MB太小的话某些操作可能会报错。实测下来2GB比较稳妥。执行完上述命令后容器会开始拉取镜像并启动。这个过程第一次比较耗时因为GitLab镜像本身就有一两个GB。启动后可以用docker ps看看容器状态大概率会显示healthy之前的启动过程里面文字是running但服务还没完全就绪。3.3 首次启动验证GitLab容器从开始启动到真正能访问中间需要很长一段时间。我见过不少同事在启动后立刻打开浏览器看到界面打不开就以为装失败了其实只是还在初始化。可以用下面的命令实时观察GitLab的启动日志sudo docker logs -f gitlab日志持续输出直到某一行看到类似这样的一段话gitlab Reconfigured! gitlab Starting gitlab...这时候GitLab基本就已经起来了。你还可以通过另一个命令确认组件状态sudo docker exec -it gitlab gitlab-ctl status正常情况下列表会显示各组件是run状态。如果其中有组件显示down那就要到后面的排查章节去找原因。打开浏览器输入你设置的hostname对应的地址。比如你设置了IP192.168.1.100那就访问http://192.168.1.100。第一次访问会跳转到一个密码设置页面这个页面是让你设置初始的管理员密码。把密码填进去并确认之后就可以用用户名root和你设置的密码登录了。这里有一个GitLab新版本的细节变化旧版本会自动生成一个随机密码存储在/etc/gitlab/initial_root_password文件里然后在首次访问时让你修改。新版本则统一在页面里完成初始密码设置。如果你访问时跳过了这个页面或者中途不小心刷新了可以通过容器命令重新查看初始密码sudo docker exec -it gitlab cat /etc/gitlab/initial_root_password文件里Password:后面的那一行就是初始密码有效期为24小时过期前记得登录修改。初次登录之后先把密码改成自己的强密码然后去看一眼首页是否正常。GitLab的欢迎页面应该已经能展示项目数、用户数等信息了。做到这一步GitLab服务器的基础搭建就算完成了。4. 配置调优与安全加固4.1 external_url与基础配置GitLab启动之后有一件事是你应该尽早在配置文件里做的明确自己的对外访问地址。打开宿主机上的挂载目录配置文件sudo vi /srv/gitlab/config/gitlab.rb找到external_url这一行把它设置成你实际的访问地址external_url http://192.168.1.100如果你是走HTTPS域名那就写成external_url https://gitlab.example.com。这个值决定了GitLab向外展示的Web地址、克隆地址、Webhook地址一定要和实际环境匹配。修改完配置文件需要让GitLab重新加载配置sudo docker exec -it gitlab gitlab-ctl reconfigure执行完reconfigure后GitLab会重新应用配置并重启相关组件。这里提醒一句每次改动配置文件后都要执行这条命令不然改动不会生效。另外如果是修改了端口映射相关的配置比如在gitlab.rb里改了Nginx监听端口或SSH监听端口光执行reconfigure不够还需要重启容器让端口映射重新对齐sudo docker restart gitlab4.2 内存与性能调优GitLab默认配置会启动很多组件其中有一部分在中小团队场景下根本用不到却白白消耗内存。我实测过在不做任何调优的情况下一台4GB的机器GitLab起来后内存几乎被吃满。所以如果你内存紧张下面这几个调整非常值得做。关闭Prometheus监控和Grafana。GitLab内置了一套监控体系在图形界面上能看到很多图表但日常用得很少。关闭它们能省下不少内存prometheus_monitoring[enable] false grafana[enable] false同时关闭非必要的后台服务。GitLab还内置了一些组件比如GitLab Pages、容器镜像仓库如果你的团队暂时用不到可以先关掉gitlab_pages[enable] false registry[enable] false修改之后同样执行gitlab-ctl reconfigure和sudo docker restart gitlab然后观察内存占用通常能从将近4GB降到2.5GB左右体验差别非常明显。Gitaly的并发参数也可以调整。Gitaly是GitLab存储层的核心组件这里的并发数决定了Git操作能否顺畅。默认的concurrency设置较保守如果你的服务器CPU核数够用可以适当提高gitaly[concurrency] [ { rpc /.*gitaly.SmartHTTPService.*/, max_per_repo 20 }, { rpc /.*gitaly.SSHService.*/, max_per_repo 20 } ]这里max_per_repo指的是每个仓库最大并发数一般在10到20之间比较合适太高了反而会拖垮磁盘I/O。另外还有一个容易被忽略但很重要的问题容器里的PostgreSQL默认使用/var/opt/gitlab/postgresql/data目录存放数据这个目录的数据增长速度可能会让你意外尤其是开启CI/CD之后构建记录和制品体积会快速膨胀。你要定期关注磁盘使用情况并且规划好数据盘的清理策略。4.3 禁止自助注册与权限设置GitLab默认开启了用户自助注册功能这是很多自建实例的安全隐患。你不希望任何人发现你的访问地址就能自己注册账号进来所以建议第一时间关闭。在GitLab Web界面以root用户登录进入 Admin Area路径是左下角的管理区。找到Settings-General-Sign-up restrictions把Sign-up enabled的勾选去掉然后保存。这样之后所有账号都由管理员手动创建团队之外的陌生人没法注册进来。同时在Settings-General-Visibility and access controls里把项目的默认可见性设置为Private。就算有人拿到了你的GitLab地址未登录状态也看不到任何项目信息。4.4 备份策略与恢复演练备份是GitLab运维里绝不能跳过的一环。GitLab官方提供了内置的备份命令使用方法很简单sudo docker exec -it gitlab gitlab-backup create这条命令会调用GitLab内部的备份工具将数据库、仓库数据、附件等打包成一个tar文件默认存放在/var/opt/gitlab/backups目录下对应宿主机路径就是/srv/gitlab/data/backups。但这里有个很多人会忽略的坑gitlab-backup create默认只备份GitLab的应用数据不包含配置文件gitlab.rb和SSH密钥、TLS证书。也就是说只靠这个备份你的GitLab实例也恢复不完整。正确的备份策略应该是两部分第一部分通过gitlab-backup create备份应用数据。 第二部分手动备份/srv/gitlab/config整个目录里面包含配置文件和密钥。备份文件生成后还要考虑异地保存。最简单的做法是写一个定时任务每天凌晨把备份目录同步到另一台机器或者云存储0 2 * * * sudo docker exec gitlab gitlab-backup create 30 2 * * * rsync -av --delete /srv/gitlab/data/backups/ /mnt/backup/gitlab/光有备份不算完你最好在某台闲置机器上真正执行一次恢复演练确保备份文件能正常还原出来。恢复命令是sudo docker exec -it gitlab gitlab-backup restore BACKUP备份文件时间戳恢复过程中GitLab会要求确认它会提示你“该操作会覆盖当前数据”确认后开始还原。这里有个经验恢复前最好把GitLab服务停掉再执行恢复否则数据在写入过程中可能会产生冲突。具体操作是先gitlab-ctl stop puma和gitlab-ctl stop sidekiq恢复完成后再启动。5. 常见问题排查与避坑记录5.1 浏览器访问显示502这是GitLab搭建过程中出现频率最高的一个问题。现象是容器在运行gitlab-ctl status也显示组件正常但浏览器访问页面时返回502。这个错误的意思是Nginx已经跑起来了但请求没能被后端的Puma进程处理。排查顺序我建议如下第一步先看Puma是否正常运行sudo docker exec -it gitlab gitlab-ctl status puma如果状态不是run大概率是Puma进程崩了。接着看日志sudo docker exec -it gitlab gitlab-ctl tail puma日志里经常会看到内存不足导致的OOM信息。这种情形下最直接的解决办法是给服务器加Swap空间或者按第4节的调优方案关掉不用的组件。第二步如果Puma是正常的那就看看是不是数据库连不上sudo docker exec -it gitlab gitlab-ctl tail postgresqlPostgreSQL启动慢或者权限问题也会造成后端连接失败日志里一般会有具体报错。第三步确认资源配置是否足够。如果服务器只有2GB内存GitLab启动时组件之间互相争抢资源会出现启动到一半进程被杀的情况。这种问题在日志里表现得很诡异一会儿报数据库连接失败一会儿报Sidekiq未响应。遇到这类情况优先考虑先加Swap再调整配置。5.2 端口冲突与SSH异常容器启动时如果宿主机已经有人在用22端口比如你安装的OpenSSH正好占用了它那GitLab的SSH映射就会失败。这种情况最直接的错误提示是端口占用你可以在宿主机上查看端口状态sudo netstat -tlnp | grep 22有进程占用的话就把GitLab的SSH端口换掉。比如改成映射到2222端口sudo docker run --detach \ --hostname gitlab.example.com \ --publish 443:443 --publish 80:80 --publish 2222:22 \ ...然后修改gitlab.rb中的配置gitlab_rails[gitlab_shell_ssh_port] 2222修改后执行reconfigure。这一步务必记得不然你在网页上看到的clone地址还是错误的22端口。SSH另一个比较容易出现的问题是用SSH协议克隆项目时提示权限拒绝。这种情况多半不是GitLab本身的问题而是你本机没有把SSH公钥加到GitLab账号里。GitLab的SSH key管理和GitHub是同一个逻辑在用户设置的SSH Keys页面贴上你的公钥然后本地ssh -T gityour-server-ip测试连通性。测试通过后再克隆就正常了。5.3 容器重启后数据丢失这个坑看着低级实际中了不少人的招。有的人在创建容器时没有挂载数据目录或者挂载了错误的目录然后某一天容器被删除了重启了一个新容器结果所有项目全没了。排查方法很简单用docker inspect看容器挂载情况sudo docker inspect gitlab | grep -A 10 Mounts输出里应该能看到三个挂载点分别指向宿主机目录。如果发现路径不对或者挂载缺失趁现在赶紧把数据目录整理好再重建容器。GitLab的数据恢复能力只跟数据目录是否完整有关跟容器本身关系不大。容器可以随便删除重建只要数据目录在GitLab就能恢复正常。5.4 备份文件缺失或备份恢复失败备份文件找不到的情况也遇到过几次。默认备份目录在/srv/gitlab/data/backups但如果你给容器挂载数据目录时用的不是/var/opt/gitlab而是只挂载了子目录备份文件可能落在容器内部一重建容器就全丢了。所以前面强调的挂载规划一定不能偷懒。备份恢复失败的常见原因之一是备份文件和当前GitLab版本不兼容。GitLab官方文档明确说明恢复备份时建议使用同一个小版本的GitLab。也就是说备份时用的是16.10.2恢复时最好也用16.10.2或者紧接着的补丁版本。跨大版本直接恢复容易出各种奇怪问题。遇到这种情况先不要慌可以先把GitLab版本降级到备份时的版本恢复成功后再推升。还有一个容易被忽视的点恢复备份前要确保备份目录里有足够的磁盘空间恢复过程会把备份文件解压出来临时空间不够也会失败。建议备份目录预留至少当前数据两倍的空间。6. 为Spring Boot项目接入CI/CD做几个准备动作GitLab服务器起来之后离跑通Spring Boot项目的CI/CD还差几件事。这里先提前打个底方便你规划接下来的步骤。第一是在GitLab里创建一个空项目把你现有的Spring Boot代码推上去。初始设置项目可见性为Private添加好成员和权限。第二是安装GitLab Runner。Runner是执行CI任务的角色可以装在和GitLab同一台服务器上也可以装在独立的构建机上。如果你用的是Docker方式部署GitLabRunner通常同样用Docker方式部署比较省心注册时填一下GitLab服务器的URL和注册令牌即可。第三是准备一个.gitlab-ci.yml文件。这个文件定义了流水线的阶段比如编译、测试、打包、部署。Spring Boot项目里典型的流水线流程是先用Maven或Gradle编译打包接着运行单元测试然后构建一个包含Spring Boot应用的Docker镜像推送到镜像仓库最后通过SSH在目标服务器上拉取镜像并重启服务。流水线的具体写法后面可以单独开一篇详细说。第四是保证GitLab Runner能访问到构建所需的依赖源。比如Maven中央仓库、Docker镜像仓库。如果是内网环境这些依赖源需要提前搭建或者配置好镜像加速否则流水线执行到拉依赖那一步会卡很长时间。我个人在实际操作中的体会是GitLab服务器搭建这件事节奏感很重要。第一次搭建时不要着急把CI/CD全链路都配上先把代码托管跑顺把备份机制跑通让团队成员每天正常push和pull代码再逐步叠加自动化流程。服务器本身很灵活后面随时可以调整配置和加Runner不需要一开始就追求完美。但基础的前置决策比如安装方式、目录挂载、备份策略这些最好一开始就定对因为后面返工的代价比你想的大得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑