news 2026/9/9 3:45:27

GitLab迁移实战:从CentOS到Docker Compose全流程记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GitLab迁移实战:从CentOS到Docker Compose全流程记录

把 GitLab 从 CentOS 原生环境迁到 Ubuntu 上的 Docker Compose,这活儿听起来不难,但我实际动手做了一圈之后发现,真正的坑全在“你以为没问题”的地方。老实例跑了三年,仓库几十个,用户权限、CI 任务记录、Webhook 全都在里面,任何一步丢了数据都受不了。所以这次迁移我定的基调很明确:先备份,再校验,再动手,最后逐项验证,一个字节都不能少。

这篇文章把整个过程完整拆给你看,包括为什么选这个迁移路线、备份怎么做才靠谱、Compose 文件怎么配、恢复顺序为什么不能乱、以及我踩过的那些奇奇怪怪的报错(尤其是 “login failed. check api token or gitlab version” 和登录页面 422 这种)。如果你也在准备做 GitLab 迁移,或者正被迁移后的登录问题卡住,这篇文章可以直接当操作手册用。

1. 迁移背景与方案设计

1.1 为什么放弃 CentOS 原生安装

先说这台旧机器的情况。CentOS 7 原生安装的 GitLab CE,当年图省事直接用 RPM 包装的,跑了三年多,GitLab 版本停在 16.x。日常用着还行,但有几个问题越来越扎眼。

第一是升级链路太长。原生安装的 GitLab 升级必须按版本逐级往上走,跳版本升级官方直接拒绝。我中间鸽了几个版本,想一次性升到最新,结果发现得先升到中间版本、再升到目标版本,一次升级要折腾大半天,还担心某个 minor 版本的迁移脚本出问题。

第二是环境越来越脏。CentOS 7 自带的是 Ruby、PostgreSQL、Redis 这些老版本,GitLab 原生包虽然能自洽,但和系统里其他服务抢端口、抢依赖的事情发生过不止一次。最烦的是磁盘扩容,根分区当初分得太保守,Git 仓库一多,磁盘动不动就报警。

第三是 CentOS 7 本身已经停止维护了,继续跑原生环境等于一台裸奔的机器上挂着公司核心代码仓库,这个风险我担不起。与其修补旧环境,不如直接换条更省心的路。

1.2 为什么选 Ubuntu + Docker Compose

新环境选型的时候,我在“继续原生安装”和“Docker 化”之间犹豫过。原生安装在 CentOS 上踩过的坑还历历在目,而且原生安装的备份恢复虽然成熟,但换机器时一样要处理版本匹配、依赖环境、系统差异这些问题,本质上没省心多少。

Docker Compose 的好处在于“整个 GitLab 是一个黑盒”。代码、配置、数据、日志全部映射到宿主机目录,升级就是换个镜像版本然后重新 up,备份就是打包那三个数据目录,回滚更是简单到改回镜像标签再 up 一次。这种“一切皆文件”的运维方式,对要长期维护的人来说,幸福感提升不是一点半点。

具体到宿主系统,我选 Ubuntu 22.04 LTS。原因很朴素:Docker 官方对 Ubuntu 的支持最积极,内核新、cgroups 和 overlay2 的支持最省心,而且遇到问题的时候搜到的解决方案,十有八九是基于 Ubuntu/Debian 的,踩坑成本最低。

操作系统选择这步,我的建议是不要追新,LTS 版本是底线。Ubuntu 24.04 当时刚出没多久,生态兼容还需要时间验证,22.04 这种已经被大量生产环境磨过的版本,反而更稳。

1.3 迁移链路拆解:数据零丢失的关键

整个迁移其实就四步:备份、传输、恢复、验证。听起来简单,但每一步都有容易忽略的细节。

备份阶段要解决的是“数据一致性”。GitLab 运行过程中,PostgreSQL 数据库、Git 仓库、上传文件、CI 产物都在持续变化,直接拷贝文件目录的方式做出来的备份,大概率是坏的。必须用 GitLab 自带的备份工具,它内部会协调各组件状态,打出一个时间点一致的快照。

传输阶段要解决的是“完整性校验”。备份文件从旧机器传到新机器,网络中断、磁盘出错都可能导致文件损坏。我见过有人 scp 到一半没检查,恢复的时候才发现 tar 包是坏的,那才是真正的灾难。所以传输完第一步是校验哈希,而不是急着解压。

恢复阶段要解决的是“版本匹配”。GitLab 官方对备份恢复的要求是:备份文件的主版本号必须与恢复目标实例一致,最好是同 minor 版本。我用的是接近同版本的镜像,避免恢复时数据库迁移脚本跑挂。这一步是很多人栽跟头的地方,后面细说。

验证阶段要解决的是“业务可用性”。数据恢复成功不等于迁移成功。仓库能不能 clone、用户能不能登录、CI 能不能跑、Webhook 能不能触发,每个功能都要过一遍,才算真正迁移完成。

2. 备份:数据零丢失的根基

2.1 GitLab 原生备份机制

GitLab 的备份工具分新旧两个名字,老版本叫gitlab-rake gitlab:backup:create,新版本改成了gitlab-backup create,底层是同一套逻辑。

这个命令备份的东西比你想象的多:Git 仓库数据、PostgreSQL 数据库、Redis 中的队列和缓存状态、上传的附件文件、CI/CD 的构建日志和产物、容器镜像仓库数据,以及一些配置元数据。说白了,除了/etc/gitlab下的配置文件,其他和业务数据相关的东西都在备份包里。

我当时的操作很简单,SSH 登录旧机器,先看一眼当前版本号:

sudo gitlab-rake gitlab:version

然后执行备份:

sudo gitlab-backup create

备份文件默认落在/var/opt/gitlab/backups目录下,文件名格式长这样:

1699999999_2024_11_15_16.11.1_gitlab_backup.tar

前面的时间戳是备份时间,后面的16.11.1是 GitLab 版本号。这个版本号务必要记牢,后面拉取 Docker 镜像时要找匹配的版本,就是靠这个数字。

备份过程中我还做了一步额外操作:把 Puma 和 Sidekiq 停掉再备份。原因是这两个服务一个是 Web 入口、一个是后台任务执行器,备份过程中如果正好有请求写入数据库,虽然 GitLab 内部有锁机制,但为了保险起见,特别是在老实例上,我宁愿短暂停服几分钟,换一个绝对一致的数据快照。

sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq sudo gitlab-backup create sudo gitlab-ctl start sidekiq sudo gitlab-ctl start puma

如果你对停机时间敏感,不停也能备份,GitLab 的设计是支持热备的,只是我这个实例太老,稳妥优先。

2.2 配置文件与密钥的备份

这是整个迁移里最容易被忽略、又最关键的一步。很多人以为备份了那个 tar 包就够了,结果恢复完发现用户登录不了、仓库 clone 地址不对、CI 的 Runner 全部失联——大概率就是配置文件没备份。

/etc/gitlab目录下有两个东西必须单独备份:

第一个是gitlab.rb,这是 GitLab 的主配置文件。external_url、SMTP 设置、LDAP 配置、SSH 端口、备份保留策略,全在这个文件里。原生安装的/etc/gitlab/gitlab.rb就是一份 ruby DSL 格式的配置。

第二个是gitlab-secrets.json,这个文件才是真正的命根子。GitLab 用它来加密数据库里的敏感字段,比如用户的两步验证密钥、CI/CD 的 token、Webhook 的密钥等。如果这个文件丢了或者和数据库不一致,恢复完成后即使密码正确也登录不进去,因为加密解密用的密钥对不上。官方文档明确说这个文件是不可恢复的,丢了等于那部分数据永远解不开。

我当时的备份命令:

sudo tar czf /var/opt/gitlab/backups/gitlab-config-backup.tar.gz /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json

另外gitlab.rb里我配了 SSH 的 host keys,对应的文件在/etc/ssh/下,但 GitLab 自带的是/etc/gitlab/ssh_host_*这组密钥。如果不想让用户在迁移后重新信任 host key,也一起备份走。我这次顺手把/etc/gitlab/ssh_host_ecdsa_key.pub一起打包了。

2.3 备份校验与安全传输

备份文件生成完之后,先别急着传。第一步先看大小是否合理,一个跑了三年的 GitLab,仓库加数据库加 CI 产物,备份文件怎么也得几十 GB,如果你发现备份包小得离谱,赶紧检查是不是有目录挂在外部存储上没被包进去。

校验文件完整性我用的是 sha256:

sha256sum /var/opt/gitlab/backups/*.tar

记录下这个哈希值,传到新机器后再算一次,两个值要一模一样。别嫌这一步麻烦,我身边真实发生过备份文件传一半远程断了,scp 报错但生成了残缺文件,恢复的时候才发现 tar 包损坏,最后只能重新备份。哈希对上了再去解压看内容,至少能确认这个包结构是完整的。

传输方式我用的是 scp,因为旧机器有固定公网 IP,速度也够:

scp /var/opt/gitlab/backups/1699999999_2024_11_15_16.11.1_gitlab_backup.tar user@新机器IP:/srv/gitlab/data/backups/ scp /var/opt/gitlab/backups/gitlab-config-backup.tar.gz user@新机器IP:/srv/gitlab/config/

传输这个动作最好放在所有准备工作完成之后再做,避免备份文件提前放到新机器上被误删。

3. Ubuntu 环境与 Docker Compose 部署

3.1 Ubuntu 基础环境准备

新机器是一台 Ubuntu 22.04,装完后第一步是把系统包更新到最新,然后装 Docker。现在的 Docker 安装方式已经比前几年简单太多了,官方推荐用 apt 仓库安装。

sudo apt update && sudo apt upgrade -y sudo apt install -y ca-certificates curl gnupg 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 a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 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-buildx-plugin docker-compose-plugin

这里有个值得说的点:现在新版 Docker 默认自带 Compose 插件,docker compose(中间有空格)是独立的 compose 插件,不再需要单独安装docker-compose(中间有横杠)那个老版本的 Python 工具了。很多人还停留在apt install docker-compose的旧习惯里,装完发现版本很老、语法支持不全,其实直接装docker-compose-plugin就好。

验证一下:

docker --version docker compose version

然后创建 GitLab 的数据目录,我习惯统一放在/srv/gitlab下,结构清晰,备份也方便。

sudo mkdir -p /srv/gitlab/config sudo mkdir -p /srv/gitlab/data sudo mkdir -p /srv/gitlab/logs sudo mkdir -p /srv/gitlab/data/backups

这三个目录分别对应容器的/etc/gitlab/var/opt/gitlab/var/log/gitlab,映射出来之后,就算容器整个删掉重建,数据也还在。

3.2 编写 docker-compose.yml

GitLab 官方提供了 Docker 镜像和 Compose 示例,但直接抄官方配置是不够的,要结合自己的实际情况调。我最终的 Compose 文件长这样:

version: '3.6' services: gitlab: image: gitlab/gitlab-ce:16.11.1-ce.0 container_name: gitlab restart: always hostname: gitlab.example.com environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://gitlab.example.com' gitlab_rails['gitlab_shell_ssh_port'] = 2222 gitlab_rails['gitlab_rails_db_username'] = 'gitlab' gitlab_rails['time_zone'] = 'Asia/Shanghai' gitlab_rails['backup_keep_time'] = 604800 puma['worker_processes'] = 2 postgresql['shared_buffers'] = "256MB" postgresql['max_connections'] = 100 manage_accounts['enable'] = true gitlab_rails['gitlab_default_theme'] = 2 ports: - "2222:22" - "80:80" - "443:443" volumes: - /srv/gitlab/config:/etc/gitlab - /srv/gitlab/logs:/var/log/gitlab - /srv/gitlab/data:/var/opt/gitlab shm_size: '256m' healthcheck: test: ["CMD", "curl", "-f", "http://localhost/-/readiness"] interval: 30s timeout: 10s retries: 5

版本号这里我特意指定了16.11.1-ce.0,而不是用latest。原因在恢复章节会详说,简单讲就是要和备份文件的版本匹配。镜像的版本号规则是gitlab/gitlab-ce:<版本号>-ce.0

端口映射这里有个很容易踩的坑:宿主机 22 端口被系统自带的 sshd 占了。GitLab 容器内的 SSH 服务默认监听 22 端口,如果你把容器的 22 映射到宿主机的 22,就会和 sshd 冲突。解决办法是把宿主机的 2222 端口映射到容器的 22,同时通过gitlab_shell_ssh_port告诉 GitLab“我的 SSH 服务对外暴露在 2222 端口”。

shm_size这个参数也不要漏。GitLab 内置的 PostgreSQL 会用到共享内存,默认值可能太小,容器跑着跑着 Postgres 直接崩,日志里报 “could not resize shared memory segment” 之类的错。我直接给了 256MB,彻底避开这个问题。

3.3 首次启动与初始化检查

配置写好之后,启动容器:

cd /srv/gitlab sudo docker compose up -d

第一次启动会非常慢,因为容器起来之后要先跑一遍gitlab-ctl reconfigure,初始化数据库、生成密钥、配置各类组件。我当时等了大概 3 分钟才看到 Web 界面响应。这个阶段不要频繁去重启容器,给足时间让它自己初始化。

看进度用:

sudo docker compose logs -f gitlab

等到日志里出现类似 “GitLab is ready to use” 或者nginx开始监听 80 端口,就说明初始化完成了。

初始化完成后,第一次访问之前,我们还没恢复数据,此时 GitLab 里是空库。我直接在浏览器访问了一下,确认 Web 服务端口通不通。

注意这个时候不建议在浏览器里点注册或者创建项目,因为马上要恢复数据,这些操作可能会在数据库里产生脏数据,干扰后续恢复流程。

4. 数据恢复与业务验证

4.1 备份文件恢复实操

恢复前先把镜像版本和备份文件版本对一下。旧机器备份文件里带16.11.1,新机器用的镜像是16.11.1-ce.0,主版本和小版本完全一致,这条路就走对了。

如果版本不一致怎么办?我建议不要赌。GitLab 官方对备份恢复的版本要求很严格,跨大版本恢复大概率会报数据库迁移错误。如果你备份的版本太老,先按升级路径逐步升级到目标版本再备份,或者拉对应大版本的中间镜像恢复后,走 GitLab 升级流程再升到最新,千万别图省事直接跨版本恢复。

恢复的第一步,把备份文件放进容器能读到的目录。Compose 里已经把/srv/gitlab/data映射到容器的/var/opt/gitlab,所以备份文件放到宿主机的/srv/gitlab/data/backups/下,容器内路径就是/var/opt/gitlab/backups/

先把前面 scp 过来的 tar 包确认在正确位置:

ls -lh /srv/gitlab/data/backups/

接下来进到容器里,停掉 Puma 和 Sidekiq。这一步不能省,否则数据库恢复时会因为连接占用而报错:

sudo docker compose exec gitlab gitlab-ctl stop puma sudo docker compose exec gitlab gitlab-ctl stop sidekiq

然后执行恢复命令。注意BACKUP=后面只写时间戳那部分,不要带_gitlab_backup.tar后缀,也不要带版本号:

sudo docker compose exec gitlab gitlab-backup restore BACKUP=1699999999_2024_11_15_16.11.1 force=yes

恢复过程中会提示你是否要删除未关联的数据,我直接输入yes。这个删除动作清理的是备份文件里不存在、但数据库里存在的旧数据,如果选 no,后续可能出现数据库不一致。

恢复完成后再启动服务:

sudo docker compose exec gitlab gitlab-ctl start sudo docker compose exec gitlab gitlab-ctl reconfigure

reconfigure这步会自动把配置文件重新生成一遍,同时确保服务状态符合配置要求。跑完之后gitlab-ctl status看一下各服务状态,正常的话应该是run

4.2 配置恢复与端口地址修正

数据恢复完成后,接下来处理配置文件的恢复。

把之前备份的gitlab-config-backup.tar.gz解压到宿主机对应目录:

cd /srv/gitlab/config sudo tar xzf gitlab-config-backup.tar.gz sudo chown -R root:root /srv/gitlab/config

解压之后,/srv/gitlab/config目录下就应该有gitlab.rbgitlab-secrets.json了。这里有个容易踩的坑:旧机器的gitlab.rb里很多配置是给原生环境用的,比如external_url可能写的旧服务器的 IP 或域名。如果直接沿用,页面上的 clone 地址、CI 里回调地址都会指向旧地址。

所以我在恢复之后专门做了一步“改地址”的操作。把gitlab.rb里的external_url改成新域名(或者新机器 IP),同时调整 SSH 端口配置。注意合并到旧的gitlab.rb里的配置项时,千万别删了gitlab-secrets.json,那是加密数据的钥匙。

修改配置后,要触发一次 reconfigure 让配置生效:

sudo docker compose exec gitlab gitlab-ctl reconfigure

顺带说一句,如果你担心gitlab.rb里还有什么旧配置不适用,有个笨但有效的办法:先看一遍文件内容,把看不懂的选项保留,重点改external_urlgitlab_shell_ssh_port和 SMTP 配置即可。

4.3 恢复后的功能验证清单

数据恢复完、配置修正完,不代表可以收工了。我把验证项列成了一份清单逐条过,任何一项不过都不能宣布“迁移完成”。

验证 Web 登录是最基本的。用管理员账号登录,如果之前开启了 LDAP 或 OAuth,也要逐个验证。登录没问题后,看仓库列表是否和旧实例一致,重点看仓库数量。我这次迁移完后仓库数量对上了,但有些项目在旧实例上是“已归档”状态,这里也要确认归档状态是否保留。

仓库数据验证,我习惯用 SSH 方式 clone 一个仓库到本地测试。这里有个关键配置要确认:因为宿主机 22 被 sshd 占了,SSH clone 地址里的端口得是 2222,clone 时要写成ssh://git@gitlab.example.com:2222/group/project.git这种格式。跑一次git clone、改个文件提交推上去,确认推送也正常。

CI/CD 验证,找一个最小的 pipeline 手动触发一次。重点看 Runner 能不能注册回来,如果之前用的是共享 Runner,可能需要在新的 GitLab 实例上重新注册 Runner。

还有一个经常被忽略的:Webhook。去有 Webhook 的项目里看一眼,确认通知地址还是不是指向旧系统,如果有钉钉、企微群机器人通知,最好触发一个事件实测一下。

查看用户权限和数据完整性。确认各项目的成员列表、用户角色、组的层级关系都和旧实例一致。恢复完之后数据细节出现差异的情况确实存在,我在多个项目里随机抽了几个人,对照旧实例逐个核对。

5. 疑难杂症与故障排查实录

5.1 “login failed. check api token or gitlab version” 报错处理

这个报错是我迁移完成后最头疼的一个。表现是本地 IDE 的 GitLab 插件连不上新实例,提示 “login failed. check api token or gitlab version. log in via git if the version” 的英文报错,但浏览器里访问 GitLab 又完全正常。

排查起来要先理解这个报错的来源。这个提示一般来自 GitLab 的 API 客户端工具或 IDE 插件,它们在调用 GitLab API 获取用户信息时,后端返回了鉴权失败。GitLab 要求客户端 API 版本兼容,token 权限足够,HTTP 请求的 Header 正确。

排查步骤我也是按顺序来的:

先确认 GitLab 版本号是否过旧。这个报错在老版本 GitLab 上更容易触发,因为插件调用的 API 路径在新版本上有变化。我这次迁移后的版本是 16.11.1,不算老,但如果是 13.x 这种古董版本,建议先升级。

然后检查 token 本身。在 GitLab 页面右上角头像下拉菜单里选择Preferences -> Access Tokens,创建一个具有api权限的 token。token 的类型要是Personal Access Token,不能用OAuth Application Token代替。我之前遇到过有人拿 deploy token 当成个人访问 token 用,结果 API 查询用户信息时直接被拒。

接着排查网络链路。如果新机器前面有 Nginx 反向代理、CDN 或者防火墙做了请求头过滤,API 的 Authorization Header 被吞掉就会导致这个报错。用 curl 直接验证是最高效的方式:

curl -H "PRIVATE-TOKEN: 你的token" http://gitlab.example.com/api/v4/user

正常返回 JSON 中包含username字段,就说明 API 链路是通的。如果这里返回 401,再看 GitLab 的 production log:

sudo docker compose exec gitlab tail -100 /var/log/gitlab/gitlab-rails/production_json.log

日志里会记录具体的请求路径和鉴权失败原因,比猜靠谱得多。

还有一个容易忽略的:如果你在旧实例上把 GitLab 跑在 HTTPS 后面,新实例改成了 HTTP,token 在传输中没问题,但一些客户端会缓存旧协议。重启一下 IDE 或者重新添加远程仓库地址就能解决。

5.2 页面 422 错误与隐身模式之谜

恢复完成后第一次用浏览器登录,遇到了一个经典问题:输入用户名密码点登录,页面直接报 422,错误信息是 “The change you requested was rejected”。更诡异的是我试了下浏览器的隐身模式,居然能正常登录。

这个现象一出来,基本可以确定问题不是 GitLab 的账号密码,而是浏览器侧的状态和服务端不匹配。Web 登录流程里有一个 CSRF 校验机制,GitLab 会在用户访问登录页时下发一个 CSRF token,放在 session cookie 里。提交登录请求时,服务端会校验提交的 token 和 session 里的 token 是否一致,不一致就直接 422。

为什么隐身模式能登录?因为隐身模式完全新开了一个 session,没有旧域名、旧路径、旧端口留下的旧 cookie,所以 CSRF token 校验自然通过。普通模式里浏览器缓存着迁移前的_gitlab_sessioncookie,里面的 token 和当前实例对不上,登录就被拦了。

处理办法也很直接:清除这个站点所有的 cookie,重新加载页面。如果实在找不到是哪个 cookie 干扰,最简单的方式是清除浏览器全部缓存和 cookie。另外,迁移前如果用过http://旧IP访问,迁移后域名变了,浏览器可能还存在旧域名的 cookie 在跨域请求中被错误携带,把所有相关域名的 cookie 都清掉最干净。

还有一个容易忽略的坑:部署了 HTTPS 并把 HSTS 打开的话,浏览器会强制跳转 HTTPS。如果新实例还没配证书,HTTP 请求会被浏览器拦掉,页面表现可能和 422 类似。所以迁移初期我建议先不用 HTTPS,确定一切正常后再上证书。

5.3 Docker 环境下的高频坑位

GitLab 容器化后的大部分问题都和端口、权限、资源限制有关,把这些坑填上,能省掉后面一大半的头疼事。

第一个坑是端口冲突。宿主机 22 被 sshd 占用,容器里 GitLab 的 SSH 服务映射到 2222。这个前面已经说过,但这里还要再提一句:修改端口映射后,gitlab.rb里的gitlab_shell_ssh_port必须同步改成 2222,否则用户在界面上看到的 clone 地址会不带端口,git 命令连不上,得手动拼端口。

第二个坑是权限问题。Docker 容器内的进程是以 root 或特定 uid 运行的。宿主机/srv/gitlab/data/backups目录如果权限不对,容器里读不了备份文件,恢复命令会报 “Permission denied”。我当时在宿主机上跑了一句:

sudo chown -R 998:998 /srv/gitlab/data

GitLab 容器内用户git的 uid 通常是 998,把这个目录的所有权交给宿主机上的 998 uid,两边就对齐了。不同镜像版本的 uid 可能有差异,用sudo docker compose exec gitlab id git查一下最准。

第三个坑是磁盘空间。GitLab 是吃磁盘的大户,备份文件、Git 仓库、CI 产物,加起来增长速度快得吓人。迁移之前要确认/srv/gitlab所在分区预留足够空间,至少是备份文件大小的 2 倍以上。恢复过程需要临时空间来解包和数据导入,空间不足会导致恢复中断,而且这种中断的恢复现场非常难收拾。

第四个坑是 DNS 和 hostname。容器内hostname参数和external_url建议保持一致的域名。如果external_url写的是 IP 而不是域名,后面改成域名的时候又得重新 reconfigure。我一开始直接用 IP,后来为了以后迁移方便改成域名,多折腾了一次,建议一步到位写域名。

5.4 排查速查表

最后整理了一份这次迁移过程中遇到的问题速查表,按症状、原因、解法整理出来,方便你直接对照:

症状可能原因处理方式
登录页报 422,隐身模式可登录浏览器旧 cookie 导致 CSRF 校验失败清除站点 cookie,或改用隐身模式确认
IDE/API 客户端报 login failed. check api token or gitlab versiontoken 权限不足、版本过旧、代理吞 Header在 Preferences -> Access Tokens 重建 api 权限 token
恢复后用户登录提示密码无效gitlab-secrets.json 未恢复或版本不一致恢复 /etc/gitlab/gitlab-secrets.json 后 reconfigure
SSH clone 地址没有端口gitlab_shell_ssh_port 未配置在 gitlab.rb 中配置 gitlab_rails['gitlab_shell_ssh_port'] = 2222
容器内 Postgres 崩溃shm_size 太小Compose 文件里配置 shm_size: 256m 后重建容器
恢复命令提示权限拒绝备份目录属主不对容器内id git查 uid,宿主机 chown 对齐
页面能开但 clone 超时22 端口被 sshd 占用端口映射改为 2222:22,并配置 gitlab_shell_ssh_port
Pipeline 发起的 Webhook 地址是旧域名旧 gitlab.rb 配置残留修改 gitlab.rb 中 external_url 后 reconfigure

结语

这次迁移真正花时间的不是敲那几条命令,而是每做完一步都要停下来想:如果这一步出了问题,会有什么症状,怎么发现,怎么回滚。备份不校验等于白备份,配置不备份等于数据没恢复,恢复完不验证等于进度归零。这套“备份-校验-传输-恢复-验证”的流程,是我这几年做各种服务迁移总结出来的通用打法,放在 GitLab 上同样适用,放到其他有状态服务上也一样成立。

最后再分享一个迁移过程中的小技巧:新旧两台机器在切换解析之前,先在新机器的/etc/hosts里把域名指向新机器 IP,用完整域名访问一遍 GitLab,确认功能全部正常后再改 DNS。万一有问题,把 hosts 改回来就能秒切回旧实例。有了这个保底方案,整个迁移过程的心理压力都能小一大截。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 3:44:43

企业数字化协作底座:从统一身份到流程引擎的落地指南

你的企业&#xff0c;需要一个数字化协作底座这件事我憋了很久想聊。做了这么多年的企业数字化落地&#xff0c;我见过太多企业把“数字化协作”理解成“上一套OA”“买个企业微信”“拉个钉钉群”——结果钱花了、工具也上了&#xff0c;跨部门协作还是靠吼&#xff0c;审批还…

作者头像 李华
网站建设 2026/9/9 3:40:21

3-5人嵌入式软硬件一体化团队为何是量产最优解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 3:39:49

PHP导出Excel实战:PhpSpreadsheet库从入门到大数据量优化

后台管理系统待久了&#xff0c;你会发现“导出Excel”几乎是个躲不掉的硬需求。运营要日报、财务要对账、销售要客户清单&#xff0c;反正只要项目里存在列表数据&#xff0c;就一定会有人过来问&#xff1a;“这个能导成Excel吗&#xff1f;”说实话&#xff0c;PHP做表格导出…

作者头像 李华
网站建设 2026/9/9 3:37:05

OpenGL实时渲染毛笔字:笔锋建模与着色器实现

简介&#xff1a;这是一份面向图形学爱好者的OpenGL毛笔字渲染算法源码包&#xff0c;基于VC开发环境实现。核心思路是利用OpenGL纹理映射与笔迹轨迹处理&#xff0c;模拟真实毛笔的粗细、干湿和飞白效果&#xff0c;适合学习非真实感渲染、纹理笔刷或书法特效开发的读者。包内…

作者头像 李华
网站建设 2026/9/9 3:35:41

ARM Trusted Firmware深度解析:架构、安全审计与平台移植实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华