我从 2016 年开始在公司内部搭 GitLab,当时团队从 SVN 迁移到 Git,选型时纠结过 GitLab 和 Gitea,最终还是定了 GitLab。这中间踩过的坑、填过的雷,说多不多说少不少,但每次看到有人还在为安装、clone 地址、Runner 触发这种基础问题卡住,就觉得有必要把这些东西一次性整理清楚。这篇文章不是官方文档的翻译,是我多年折腾 GitLab 的经验汇总,从部署方式选型到日常使用,从报错排查到 CI/CD 实践,尽量让你看完就能上手。
1. 动手安装前:部署方式选型与硬件规划
1.1 Docker、Omnibus 包还是源码编译:我为什么推荐 Docker
很多刚接触 GitLab 的人第一个问题是"到底该怎么装"。GitLab 官方提供三种主要方式:
- Omnibus 安装包:官方推荐的 RPM/DEB 包,把所有组件打包在一起,适合直接装在物理机或云服务器上。
- Docker 容器:一条命令拉起整个实例,适合测试环境或已有容器平台的团队。
- 源码编译:最灵活但最折腾,只适合二次开发场景,普通人没必要碰。
我在生产环境里两种都长期用过。如果你问我现在新项目怎么选,我建议先看团队现状:
- 运维能力薄弱、图省事的,直接用 Omnibus 包,
apt install一条命令完事,配置集中在一个/etc/gitlab/gitlab.rb文件里。 - 已经有 Docker Compose 或 Kubernetes 的团队,优先走容器化路线,迁移、备份、扩容都方便。
- 公司有统一资产管理要求、需要用 Ansible 等工具批量管理的,Omnibus 更契合传统运维习惯。
个人做实验或小团队内部使用,Docker 是最快见效的方案。我接下来重点讲 Docker 方式,因为它的坑最多,讲清楚了基本能覆盖各类问题的起因。
1.2 硬件配置与域名端口规划:内存不足是新手最大的坑
GitLab 是出了名的吃内存,这是所有组件(PostgreSQL、Redis、Sidekiq、Gitaly、NGINX 等)叠加的结果。官方给出的参考配置是至少 4GB 内存跑小型团队(约 100 用户),但我实测下来:
| 场景 | 最低配置 | 建议配置 |
|---|---|---|
| 个人实验/小团队(<10人) | 2GB 内存 + 2核 | 4GB 内存 + 4核 |
| 中型团队(10~100人) | 4GB 内存 + 4核 | 8GB 内存 + 8核 |
| 大型团队(>100人)或重度 CI | 8GB 内存 + 8核 | 16GB+ 内存 |
这里要提醒:内存不够的表现不是启动失败,而是启动极慢、卡顿、502。很多人安装完了发现页面一直 502,第一反应以为是端口问题,实际上多半是内存不够,GitLab 的 Unicorn/Puma worker 起不来。我建议你在安装前就用free -h确认一下内存,如果只有 1~2GB,至少加个 swap 再装。
域名和端口规划也很关键。GitLab 默认占用的端口很粗暴:HTTP 是 80,HTTPS 是 443,SSH 是 22。这三样都是机器上的"默认端口",很容易和其他服务冲突。
- 如果你是要长期用的正式环境,提前准备一个域名,比如
gitlab.example.com,用 Nginx 反代或直接让 GitLab 用 80/443 端口都可以。 - 如果只在局域网或本机测试,可以把容器的端口映射到宿主机的其他端口上,比如
8080:80、2222:22,这样不会影响已有服务。 - 官方建议用域名而不是 IP 访问,因为后面的 clone 地址、Runner 注册地址都会基于 external_url 生成,如果这里填了
localhost,后面所有项目的 clone 路径都会是http://localhost/group/project.git,局域网其他人没法用。这个问题我在第 4 章会专门讲。
2. Docker 部署 GitLab 全流程:从镜像拉取到页面访问
2.1 环境准备与 Docker Compose 配置
我习惯用 Docker Compose 管理 GitLab,一条命令就能启动、停止,配置也清晰。先在你的服务器上确认 Docker 和 Compose 已装好:
docker --version docker compose version没有的话,Ubuntu 上执行:
curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER然后创建一个目录,比如/opt/gitlab,在里面写docker-compose.yml:
version: '3.8' services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab restart: always hostname: gitlab.example.com ports: - "80:80" - "443:443" - "2222:22" environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://gitlab.example.com' gitlab_rails['gitlab_shell_ssh_port'] = 2222 # 如果不希望用户自行注册,可以设置 gitlab_rails['gitlab_signup_enabled'] = true # 初始 root 密码(至少8位) gitlab_rails['initial_root_password'] = 'YourStrongPassword123!' volumes: - ./config:/etc/gitlab - ./logs:/var/log/gitlab - ./data:/var/opt/gitlab shm_size: '256m'几个关键点说明:
hostname和external_url最好不要写成 IP。如果临时测试实在没有域名,可以用external_url 'http://服务器IP',但后面 clone 地址就会是 IP 加端口的形式,勉强能用但不好看。- 我把宿主机的
2222映射到容器的22,因为宿主机往往已经占用了 22 端口。配合gitlab_rails['gitlab_shell_ssh_port'] = 2222,GitLab 会在展示 SSH clone 地址时自动带上2222端口,用户复制下来就能直接用。 shm_size这个参数很多人会漏掉。GitLab 的某些组件会用到共享内存,不设的话在并发高时容易出现奇怪的 500 或 502 错误。- 初始密码我建议显式设置而不是随机生成,不然第一次访问还要去容器里挖密码文件,麻烦。
2.2 启动、初始化等待与常见启动异常处理
配置写好后,启动:
docker compose up -d这时有个非常容易让新手崩溃的过程:GitLab 首次初始化需要 3~8 分钟甚至更久。在这段时间里,你访问页面大概率是 502 或者直接拒绝连接。不要慌,这是正常现象,它正在后台执行迁移、初始化数据库等操作。
你可以通过日志观察进度:
docker logs -f gitlab当看到类似GitLab ready.或Running gitlab-rake db:migrate结束、日志里出现nginx启动相关字样时,就基本就绪了。判断是否真正可用的最简单办法是等日志逐渐安静后,再访问http://你的域名或IP。
初始化期间如果容器反复重启,多半是内存不够或配置不对。先把容器日志发出来看,不要急着删了重装。走sudo docker logs gitlab能看到具体报错。
在所有组件启动完成后,用 root 用户和刚才设置的密码登录,第一件事是进入Admin Area → Settings做一些基础安全设置。比如是否开放用户注册、是否需要管理员审核新用户,这直接关系到后面那个"pending approval"报错。
2.3 Omnibus 包安装作为备选方案
如果你不想用 Docker,想直接在 Ubuntu 上装,命令如下:
sudo apt-get update sudo apt-get install -y curl openssh-server ca-certificates tzdata perl curl -fsSL https://packages.gitlab.com/gitlab/gitlab-ce/packages/ubuntu/jammy/gitlab-ce_XXX_amd64.deb/download -o gitlab-ce.deb sudo dpkg -i gitlab-ce.deb sudo gitlab-ctl reconfigure或者用官方推荐的脚本:
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash sudo apt-get install gitlab-ce sudo gitlab-ctl reconfigure安装完后,编辑/etc/gitlab/gitlab.rb,把external_url改成你的域名或 IP,然后再次sudo gitlab-ctl reconfigure。这套方式中所有配置都在一个文件里,改完后统一 reconfigure,逻辑上更直观,也方便用配置管理工具自动化。
3. 日常高频操作:账号、仓库、SSH 与 Clone 地址
3.1 注册账号、"pending approval" 报错的根源与处理
GitLab 的账号注册这块,不同团队配置不一样。如果你的 GitLab 开启了开放注册(默认是关闭的,由管理员在 Admin Area → Settings → General → Sign-up restrictions 里控制),用户可以直接在登录页点 Register 自己注册。但如果管理员开启了"Require admin approval for new sign-ups",新用户注册后就会看到:
Your account is pending approval from your GitLab administrator and hence blocked. Please contact your GitLab administrator.
这个报错在热搜词里出现了,说明卡在这里的人相当多。这不是你的账号有问题,也不是密码设置不对,纯粹是管理员还没有审核。处理方式:
- 作为普通用户,你只能联系管理员,让他去Admin Area → Users,找到你的账号,点击Approve。
- 作为管理员,你也可以在注册设置里关掉审核要求,或者直接在用户列表批量批准。
在企业里,管理员通常都会开着这个开关,目的就是防止垃圾账号注册进来乱建仓库。所以你遇到这个提示,第一时间去行政群或邮件联系管理员就好,这不是技术故障。
3.2 创建、导入与删除仓库:UI 操作与管理命令
创建仓库在 GitLab 上极其简单,点New project,选Create blank project,填个名字就行。但有几个细节容易被忽略:
- 仓库可见性建议一开始就选Private或Internal,别选 Public。Public 在公网部署下等于裸奔,代码直接暴露给搜索引擎。内网部署倒是无所谓,但养成习惯总没坏处。
- 初始化时勾选Initialize repository with a README,这样克隆下来就有默认分支,省得你推空仓库时还要先建分支。
导入已有仓库是团队迁移时的高频操作。GitLab 支持从 GitHub、Bitbucket、SVN 等导入,也能直接导入 URL。我用的最多的是 URL 导入:在 New project → Import project → Repository by URL 里填上游仓库地址。如果你是导自己的 GitLab 到另一个 GitLab,记得用HTTP方式而不是 SSH,因为你自己的 SSH key 在源服务器上可能没配置,反而麻烦。
删除仓库的路径有点反直觉:不是在仓库首页,而是Settings → General → Advanced → Delete project。敲一遍项目名确认后才会真正删除。这里提醒一点:删掉的仓库很难恢复,尤其是如果你没开 GitLab 的回收站功能,删除操作是不可逆的。正式环境建议先做一个仓库级别的导出备份(Settings → General → Advanced → Export project),再删除,以防手滑。
3.3 配置 SSH 密钥与 HTTPS Clone 时的账号密码认证
GitLab 的 clone 方式有两种:HTTP(S) 和 SSH。团队里很多新人第一次 clone 都习惯直接复制 HTTP 地址,然后每次 push 都要输账号密码,输错了还会被 Git 缓存住,后面想换账号都费劲。
我的建议是:能用 SSH 就用 SSH,一劳永逸。配置方法:
# 1. 生成密钥对(如果还没有的话) ssh-keygen -t ed25519 -C "youremail@example.com" # 2. 把公钥加到 GitLab cat ~/.ssh/id_ed25519.pub # 把输出的内容复制到 GitLab:右上角头像 → Preferences → SSH Keys → Key 框里粘贴 → Add key这里有个小技巧:ssh-keygen时不用一路回车,建议给私钥设置一个 passphrase,就算私钥泄漏别人也打不开。Git 每次连接时会自动调用 ssh-agent,输入一次 passphrase 后本次会话不用重复输。
测试密钥是否生效:
ssh -T git@gitlab.example.com看到Welcome to GitLab, @username!就说明通了。如果你是按我前面第 2 章那样把容器 22 端口映射到宿主机 2222 的,记得测试命令是:
ssh -T -p 2222 git@gitlab.example.com很多人配了密钥却 clone 失败,大概率就是漏了自定义端口。
3.4 本地 Git 客户端同时配置 GitHub 和公司 GitLab
很多开发者电脑上同时有 GitHub 个人项目和公司 GitLab 项目。默认情况下 Git 看到同一个git@前缀的地址,会混淆用哪把密钥。解法是按域名区分 Host 配置~/.ssh/config:
# GitHub Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github # Company GitLab Host gitlab.example.com HostName gitlab.example.com User git Port 2222 IdentityFile ~/.ssh/id_ed25519_gitlab这样执行git clone git@github.com:xxx/yyy.git时自动用 GitHub 的密钥,clone 公司 GitLab 时自动用公司密钥。这个配置文件是解决"本地 Git 客户端如何同时适配 GitHub 和公司 GitLab"的标准答案。
注意:如果你有多把密钥,且没有配~/.ssh/config,Git 默认会尝试~/.ssh/id_rsa或id_ed25519这把默认密钥,连不上就报 permission denied。所以配置好别名是正解,而不是把公司密钥复制成默认文件名。
3.5 IDEA 等 IDE 里的账号切换问题
在 IntelliJ IDEA 里切换 GitLab 账号,很多人的操作是去 Settings → Version Control 里改账号,但实际 git 操作还是用的旧账号。原因在于 IDE 的认证信息存在系统凭证管理器或 Git 的 credential helper 里。
处理办法是清理 Git 缓存的凭证:
# 查看当前 credential helper git config --global credential.helper # 清理已保存的认证信息(macOS 用 osxkeychain,Windows 用 manager-core) printf "protocol=https\nhost=gitlab.example.com\n\n" | git credential-osxkeychain eraseWindows 上是:
git credential-manager-core uninstall或去"控制面板 → 凭据管理器 → Windows 凭据"里找到 GitLab 相关条目手动删除。删完后再操作一次 clone 或 push,IDE 会重新弹出输入框让你输新账号密码。
其实切换到 SSH key 认证后,这种账号切换问题会大幅减少。SSH 的 key 是跟着用户走的,IDE 在哪个用户上下文下执行 git 命令就用哪个 key,不会反复弹出登录框。
4. 高频报错排查:从登录验证失败到 Clone 地址错误
4.1 "login failed. check api token or gitlab version" 的完整排查链路
这个报错经常出现在 Jenkins、GitLab API 脚本或第三方工具集成 GitLab 时,完整报错一般是:
ERROR: Connection refused! Please check if the GitLab server is reachable or check your api token. Login failed. check api token or gitlab version. Log in via git if the version > 4.5
这个报错的字面意思是:客户端尝试用 API token 登录 GitLab 失败,同时提示"如果版本大于 4.5 请走 git 方式登录"。出现这个报错时我建议按下面顺序排查:
第一步:确认 token 本身有效。打开 GitLab → 右上角头像 → Preferences → Access Tokens,确认是否已创建 token、token 是否过期、权限是否包含api。如果 token 过期,直接生成一个新的,这个报错里有 90% 都是 token 过期或填错导致的。
第二步:确认 GitLab 地址可达。在 Jenkins 服务器上执行:
curl -I http://gitlab.example.com/api/v4/projects?private_token=你的token如果返回 200 或 401,说明网络没问题;如果超时或 DNS 解析失败,说明 Jenkins 根本访问不到 GitLab,问题在网络层而不是 token。
第三步:确认 GitLab 版本兼容性。GitLab API 在不同大版本之间有破坏性变更,老版本的插件或脚本连新版 GitLab 很容易报错。Jenkins 的 GitLab Plugin 有"使用较新的 GitLab API"选项,勾上或升级插件版本,通常能解决大部分版本不兼容问题。
第四步:如果是在 Jenkins 里配置 GitLab Connection 时报错,进入 Jenkins → Manage Jenkins → Configure System → GitLab,检查 Connection name、GitLab host URL、Credentials 是否对得上。Credentials 里的 API Token 应为 Personal Access Token,而不是用户密码。这一点很多人填错。
4.2 Clone 地址显示成机器 ID 或 localhost 的处理
前面我在部署时特意强调了external_url,现在来说说如果你没设对会看到什么。
公司里经常出现这种场景:GitLab 装在服务器上,开发者在本地打开项目页面,看到的 clone 地址是:
http://localhost/group/project.git或者:
http://机器名/group/project.git这基本就是external_url配错了。我之前帮人排查过一台 GitLab,他用docker run启动时只给了-p 8080:80,但 environment 里GITLAB_OMNIBUS_CONFIG根本没设置external_url,导致 GitLab 默认用容器的 hostname(一串容器 ID)生成 clone 地址。
修复方法:
- 用 Docker Compose 的,修改
external_url为目标域名或 IP。 - 用 Omnibus 包的,修改
/etc/gitlab/gitlab.rb里的external_url。 - 改完后重新配置并重启:
docker compose up -d # 或 sudo gitlab-ctl reconfigure有个细节值得注意:如果用户复制了旧地址http://localhost/group/project.git到本地,而 GitLab 服务器跟你的开发机不在同一台机器上,这个地址必然 clone 不了。这种问题不是网络故障,而是地址本身错了。内部使用建议直接用http://服务器IP/group/project.git或http://gitlab.company.com/group/project.git,并且保证所有开发机器都能解析这个域名(走内网 DNS 或改 hosts 都行)。
4.3 没有 .gitlab-ci.yml 依然触发 Runner:原因与对策
这个现象我遇到过好几回。团队里配好了 Shared Runner,然后在项目里点了一下 CI/CD → Run pipeline 的按钮,即使仓库里根本没有.gitlab-ci.yml,Runner 也会被触发。还有更迷惑的:只是把空项目设置为"Auto DevOps",也会尝试执行流水线。
原因是 GitLab CI 在判断"是否需要 runner"时,有几个默认行为:
- 开启了 Auto DevOps 的项目,如果没有检测到
.gitlab-ci.yml,GitLab 会自动生成默认的流水线配置。 - 在 UI 里手动点击Run pipeline时,如果选择分支上没有
.gitlab-ci.yml,GitLab 会提示你选 Auto DevOps 模板,确认后就会执行。 - 某些 runner 配置了
run_untagged,且项目和 runner 都未限制 tag,此时只要有 pipeline 被创建,runner 就会去接活。
如果你不希望这种行为出现,最稳妥的方式是把项目的Auto DevOps关掉:Settings → CI/CD → General pipelines → 取消勾选 Auto DevOps。同时让 Runner 在注册时绑定 tag,比如 tag 为docker,项目中只有 job 里写了tags: [docker]才会触发这个 Runner,其他 pipeline 就不会被它执行。
很多人误以为"只要放一个 Runner,项目就会自动跑流水线",实际上 Runner 只是执行者,谁来创建 pipeline 才是关键。pipeline 的创建来源包括代码中带了.gitlab-ci.yml、手动点击 Run pipeline、合并请求时触发、定时任务、Auto DevOps 自动生成。把这些来源捋清楚,"没有 yaml 依然触发"的疑问自然就解开了。
4.4 GitLab 高危漏洞修复的基础思路
热搜词里有"GitLab 高危漏洞修复方案",这里也一并说说。GitLab 历史上出过不少被公开利用的漏洞,比如 RCE、SSRF、路径穿越之类。实际上 GitLab 的漏洞修复,绝大多数情况就是升级版本。
修复路径是:
- 确定当前版本:
docker exec gitlab cat /opt/gitlab/version-manifest.txt | head -n 5 # 或 cat /opt/gitlab/version-manifest.txt- 去官网查看你版本之后的补丁版本,每个月的安全发布都会列出来,找出包含安全修复的最新版本。
- 升级到目标版本(Docker 方式直接换 tag 重启):
docker compose pull gitlab docker compose up -d这里有个公司里经常被忽视的点:跨大版本升级必须逐级来,比如 16.x 升 17.x,不能直接跳很多个大版本,否则数据库迁移会失败。GitLab 官方有升级路径文档,升之前先确认当前版本到目标版本之间是否有中间版本需要走一遍。升级前务必备份/etc/gitlab、/var/opt/gitlab对应 volume,放本地一份,最好再拷到异地。
如果想减少漏洞暴露面,还有几个操作可以做:
- 在 Nginx 或防火墙层面,把 GitLab 的 Web 页面限制为内网访问,不让公网直接访问。
- 开启两步验证(2FA),特别是管理员账号。
- 关掉不必要的自注册,避免陌生账号进来。
- 定期检查 Admin Area → Security 页面的报警和系统审计日志。
5. GitLab CI/CD 实践:Runner 配置与自动化部署
5.1 注册 GitLab Runner:项目级与共享级
GitLab CI/CD 的架构很简单:代码变更触发 pipeline,pipeline 里有 job,job 被分配到 Runner 上执行。Runner 需要单独安装和注册,不会随 GitLab 自动装好。
注册 Runner 的标准流程:
- 在 GitLab 项目里拿到注册 token:Settings → CI/CD → Runners,或者 GitLab 管理员的共享 Runner 入口。
- 在目标机器上安装 Runner:
# 以 Linux + Docker executor 为例 curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 chmod +x /usr/local/bin/gitlab-runner- 注册:
sudo gitlab-runner register \ --url http://gitlab.example.com \ --token 你的token \ --executor docker \ --docker-image docker:latest \ --docker-volumes /var/run/docker.sock:/var/run/docker.sock \ --tag-list docker \ --run-untagged=true这里最关键的是最后那条/var/run/docker.sock挂载,很多人在 CI 里想 build Docker 镜像或直接 docker run 服务,Runner 里执行 docker 命令却报"cannot connect to the Docker daemon",就是因为没把宿主机的 Docker socket 挂进来。挂载后,runner 容器内执行的 docker 命令就能直接操作宿主机的 Docker 守护进程,也就是俗称的"docker 里跑 docker"。
5.2 .gitlab-ci.yml 实战:Docker 镜像构建与自动部署
一个最基本的 Java 项目 .gitlab-ci.yml 大概是这样的:
stages: - build - test - deploy variables: MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2" cache: paths: - .m2/ build: stage: build image: maven:3.9-eclipse-temurin-17 script: - mvn clean package -DskipTests artifacts: paths: - target/*.jar expire_in: 1 week deploy: stage: deploy image: docker:latest services: - docker:dind script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA only: - main几个容易踩坑的地方:
- services: docker:dind是让 CI 环境里能启动 Docker daemon 的做法,和挂载
/var/run/docker.sock是两种不同思路。前者适用于 Runner 本身就在容器里、且无法直接访问宿主机 socket 的场景;后者适合 Runner 在宿主机上直接跑的情况。两种方式选一种就行,别同时用,容易乱。 $CI_REGISTRY_IMAGE是 GitLab 自带 CI/CD 变量,指当前项目的内置容器镜像仓库地址。用 GitLab 内置 registry 可以免去单独搭建镜像仓库的麻烦。only: [main]代表只有 main 分支的改动才触发 deploy。如果要走合并请求流程,可以用rules来精细化控制,比如合并请求的 job 用if: '$CI_PIPELINE_SOURCE == "merge_request_event"'。
部署环节,常见做法是通过 SSH 登录目标服务器执行部署脚本,或者用 Kubernetes 的 kubectl 更新镜像版本。我这里给一个最通用、也最容易被新手理解的 SSH 方案:
deploy-prod: stage: deploy image: alpine:latest before_script: - apk update && apk add openssh-client - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | ssh-add - - mkdir -p ~/.ssh - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts script: - scp -r target/*.jar deploy@prod-server:/opt/app/ - ssh deploy@prod-server "cd /opt/app && ./restart.sh" environment: name: production only: - tags这个 job 用到了SSH_PRIVATE_KEY和SSH_KNOWN_HOSTS两个 CI/CD 变量,需要提前在项目的 Settings → CI/CD → Variables 里配好。environment: production的好处是 GitLab 会在 CI/CD → Environments 页面记录每次部署和对应版本,回滚和追溯都方便。
5.3 Jenkins 与 GitLab 集成要点
虽然 GitLab 自带 CI/CD,但很多企业已经有 Jenkins 了,需要把两者打通。Jenkins 配 GitLab Connection 时,核心就两件事:在 GitLab 创建 Access Token,在 Jenkins 里配置 Credentials 并测试连接。
具体步骤:
- GitLab 用户生成 Personal Access Token(勾选
api权限)。 - Jenkins → Manage Jenkins → Credentials → Global,添加一个"GitLab API token"类型的凭证。
- Jenkins → Manage Jenkins → Configure System,找到 GitLab 部分,填 Connection name(随意,比如"Company GitLab")、GitLab host URL(填
http://gitlab.example.com而不是项目路径)、Credentials(选刚才创建的凭证)。 - 点Test Connection,返回 Success 就代表通了。
- Jenkins 里创建多分支流水线项目时,在源码管理里选 Git,仓库地址填 GitLab HTTP 地址,Credentials 用刚才的凭证即可。
Jenkins 触发 GitLab pipeline 常见报错就是我 4.1 节讲的那个 "login failed. check api token or gitlab version"。这里再补充一个冷知识:如果 Jenkins 所在的服务器 DNS 解析不到 GitLab 的域名,也会报连接超时,但错误信息不会明说 DNS 问题,你会误以为是 token 错了。所以遇到登录失败,先 curl 一遍再排查凭证。
另外,现在 GitLab 官方在推荐用GitLab Jenkins Plugin来做 Webhook 触发,配置路径是 GitLab 项目 → Settings → Webhooks,URL 填http://jenkins.example.com/project/你的流水线项目名,Secret Token 填 Jenkins 侧配置的相同 token。Webhook 事件勾选 Push events 和 Merge request events 即可。
5.4 Runner 并发与 tag 策略对团队的影响
Runner 配多了以后会遇到一个问题:多个项目共享同一个 Runner,某个项目的构建任务把 Runner 资源耗尽,其他项目的任务全部排队。这种场景下我建议给 Runner 做分类:
- 共享 Runner(Shared):配给所有项目,适合 label 为
docker的通用构建任务,如 maven 构建、npm 构建。 - 项目专属 Runner(Specific):给某几个重量级项目单独部署,避免被其他项目抢占。
- tag 策略:每个 Runner 注册时指定 tag(比如
linux、gpu、docker),在.gitlab-ci.yml里用tags:字段选择特定 Runner 执行。
如果团队 pipeline 经常排队,先看一下Admin Area → CI/CD → Runners页面里每个 Runner 的在线状态和任务负载,再考虑扩展 Runner 数量,而不是盲目加机器。
6. 备份恢复与数据安全
6.1 GitLab 自带备份命令与定时备份
GitLab 备份是很多管理员容易忽略的事情。GitLab 自带的备份命令其实很简单:
# 容器方式 docker exec -t gitlab gitlab-backup create # Omnibus 方式 sudo gitlab-ctl backup-etc sudo gitlab-backup create备份文件默认存放在/var/opt/gitlab/backups,对应 Docker volume 就是./data/backups。备份内容主要包含数据库、Git 仓库、上传文件等。注意:备份命令不会自动备份配置文件,比如/etc/gitlab/gitlab.rb(Docker 方式对应./config目录)。要恢复一套完整的 GitLab,配置和备份数据缺一不可。
所以我在生产环境推荐的备份策略是:
- 每天凌晨用 crontab 跑一次
gitlab-backup create。 - 同时用
tar把./config目录打包备份到远端存储(如云对象存储、公司 NAS)。 - 备份保留至少 7 天,方便回滚到任意一天。
一个简单的 crontab 示例:
0 3 * * * docker exec -t gitlab gitlab-backup create 2>&1 >> /var/log/gitlab-backup.log6.2 从备份中恢复的完整步骤
恢复 GitLab 比备份稍微麻烦一点,因为涉及到停止相关服务、替换备份文件。流程如下:
- 把备份文件复制到容器的备份目录:
./data/backups/,文件名格式应为1712345678_2024_04_06_16.9.0_gitlab_backup.tar。 - 停止与数据库相关的组件,防止恢复过程中写入冲突:
docker exec -t gitlab gitlab-ctl stop puma docker exec -t gitlab gitlab-ctl stop sidekiq docker exec -t gitlab gitlab-ctl stop postgresql- 执行恢复命令:
docker exec -t gitlab gitlab-backup restore BACKUP=1712345678_2024_04_06_16.9.0这里 BACKUP 参数必须填备份文件时间戳那一串,不含扩展名。 4. 等待提示done后,重启容器:
docker restart gitlab恢复后如果发现版本不对(比如备份来自更高版本),GitLab 会拒绝恢复,这是正常的。最佳实践是备份和恢复都在同一大版本内完成。
7. 我踩过的一些坑:写在最后的经验心得
GitLab 从安装到维护这么多年,我总结出几条不一定写进官方文档、但真的会影响使用体验的经验:
第一,给 GitLab 预留足够的磁盘空间。代码仓库本身不大,但 Docker 镜像、CI 产物、容器 Registry 会以惊人速度膨胀。我见过一台机器部署 3 个月后磁盘满了,GitLab 直接拒绝写入,所有 push 都失败。现在我的习惯是给 GitLab 数据目录单独挂一块大磁盘,并且配置 CI 产物的过期时间(artifacts expire_in),定期清理无用的容器镜像。
第二,external_url 一定要在第一时间设置正确。这东西影响范围比你想的大得多,不只是页面显示问题,还关系到推送地址、Runner 注册地址、Webhook 回调地址。项目上线早期改起来容易,等到几十个人都在用了,一改 external_url 会导致所有 clone 地址失效。但即便如此,也比一直用一个错误地址强。国内网络环境下尤其建议使用自定义域名,而不是只用机器 ID 或 localhost。
第三,普通项目我推荐直接把 CI/CD 用起来。很多团队把 GitLab 只当成代码托管的 Git 服务器,其实它自带的 CI/CD 在中小团队内部完全够用,跑测试、构建镜像、自动部署到服务器,都是开箱即用。而且它和 MR 的集成非常自然,逻辑清晰,比外部 Jenkins 少一层配置。如果要上 Kubernetes,GitLab 还有 Agent 集成,后面可以顺滑演进。
第四,版本升级不要拖延。GitLab 基本每个季度会有一个安全发布版本,其中包含多个高危漏洞修复。拖版本升级的真正成本在于跨大版本升级时需要逐级处理,越拖越不敢升。就算不在第一时间升,也要至少每个大版本跟上一次。
这篇文章覆盖了从安装部署到日常使用、报错排查、CI/CD 落地、备份恢复的主要场景。你在实际使用过程中如果还有更细致的问题,比如某些版本特有的配置变化、Runner 执行器的细节参数,建议先去 GitLab 官方文档确认对应版本的说明,再结合自己的环境调整。毕竟 GitLab 更新很快,版本差异带来的细节改动也不少。