250829-Gitlab数据备份与恢复


下面给你一份可落地的迁移方案 ,保证 GitLab 的数据和配置完整迁移到服务器 B。你当前用的是 GitLab Omnibus(docker 版),数据都在你映射的 3 个目录里(/etc/gitlab, /var/log/gitlab, /var/opt/gitlab),迁移就是把这些目录搬过去,然后用同版本镜像在 B 上启动即可。


方案 A:直接拷贝挂载卷(最简单、最稳妥)

适合:两台机子都能互通 SSH,短暂停机可接受。

1) 在 A 上停 GitLab,确保数据静止

bash 复制代码
# 看容器名
docker ps
# 停
docker stop gitlab
# 确认都停了(也避免有自动重启)
docker update --restart=no gitlab

2) 打包或 rsync 同步 3 个目录到 B

任选其一(rsync 或 tar),二选一即可

方式一:rsync(推荐,能保留权限/硬链接)

bash 复制代码
# 在 A 上执行,把整个 gitlab 目录同步到 B
rsync -aHAX --numeric-ids --info=progress2 -e ssh \
  /home/liuguokai/docker/data/gitlab/ \
  user@服务器BIP:/home/liuguokai/docker/data/gitlab/

方式二:tar 打包

bash 复制代码
# A 上打包
sudo tar -C /home/liuguokai/docker/data/gitlab -cpf /tmp/gitlab-volumes.tar etc log opt
# 传到 B
scp /tmp/gitlab-volumes.tar user@服务器BIP:/tmp/
# B 上解包到相同路径
sudo mkdir -p /home/liuguokai/docker/data/gitlab
sudo tar -C /home/liuguokai/docker/data/gitlab -xpf /tmp/gitlab-volumes.tar

说明:一定要保留文件权限/属主(-aHAX --numeric-ids 或 tar 的 -p)。

3) 在 B 上用同一版本镜像启动

建议先在 A 上看用的镜像 tag(避免"latest"漂移导致版本不一致):

bash 复制代码
# A 上查看容器使用的镜像名:tag
docker inspect gitlab --format '{{.Config.Image}}'
# 例如得到:gitlab/gitlab-ce:16.11.2-ce.0  (示例)

然后在 B 上拉取同版本并启动(端口可按需改):

bash 复制代码
# B 上
docker pull gitlab/gitlab-ce:你的准确版本tag

docker run -itd \
 -p 5004:80 \
 -p 5005:22 \
 -v /home/liuguokai/docker/data/gitlab/etc:/etc/gitlab \
 -v /home/liuguokai/docker/data/gitlab/log:/var/log/gitlab \
 -v /home/liuguokai/docker/data/gitlab/opt:/var/opt/gitlab \
 --restart always \
 --privileged=true \
 --name gitlab \
 --shm-size 1g \
 gitlab/gitlab-ce:你的准确版本tag

4) 首次启动检查与收尾

bash 复制代码
# 跟日志,等服务健康
docker logs -f gitlab
  • 如果 B 的访问地址/域名变了,修改 /etc/gitlab/gitlab.rb 里的 external_url,然后:

    bash 复制代码
    docker exec -it gitlab bash -lc "gitlab-ctl reconfigure && gitlab-ctl restart"
  • 验证:Web 能打开、项目可拉取/推送、CI pipeline 能跑、SSH 端口(你是 5005)能连。


方案 B:使用 GitLab 内建备份/恢复(适合跨大版本或想最小化拷贝量)

会多一步"备份→恢复",但也很正规。同样需要备份 gitlab-secrets.jsongitlab.rb

1) 在 A 上创建应用级备份

bash 复制代码
# 停应用前先做一次在线备份也可以;若严格一致性,先 stop 再备份
docker exec -t gitlab gitlab-backup create
# 也可用:docker exec -t gitlab gitlab-rake gitlab:backup:create

备份文件会在容器内 /var/opt/gitlab/backups/,你映射到了宿主 /home/liuguokai/docker/data/gitlab/opt/backups/。同时单独备份

  • /etc/gitlab/gitlab.rb
  • /etc/gitlab/gitlab-secrets.json

2) 把备份文件和两个配置文件复制到 B

bash 复制代码
# 例如:
scp /home/liuguokai/docker/data/gitlab/opt/backups/*_gitlab_backup.tar user@B:/tmp/
scp /home/liuguokai/docker/data/gitlab/etc/gitlab.rb user@B:/tmp/
scp /home/liuguokai/docker/data/gitlab/etc/gitlab-secrets.json user@B:/tmp/

3) 在 B 上启动干净容器(同版本),再恢复备份

bash 复制代码
# 先启动空实例(用你习惯的挂载路径)
docker run -itd \
 -p 5004:80 -p 5005:22 \
 -v /home/liuguokai/docker/data/gitlab/etc:/etc/gitlab \
 -v /home/liuguokai/docker/data/gitlab/log:/var/log/gitlab \
 -v /home/liuguokai/docker/data/gitlab/opt:/var/opt/gitlab \
 --restart always --privileged=true --name gitlab --shm-size 1g \
 gitlab/gitlab-ce:你的准确版本tag

# 将备份和配置放到对应卷里
mv /tmp/*_gitlab_backup.tar /home/liuguokai/docker/data/gitlab/opt/backups/
mv /tmp/gitlab.rb /home/liuguokai/docker/data/gitlab/etc/
mv /tmp/gitlab-secrets.json /home/liuguokai/docker/data/gitlab/etc/

# 执行恢复(文件名按实际改)
docker exec -it gitlab bash -lc '
gitlab-ctl stop puma && gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP=备份文件名前缀(例如 1724839200_2025_08_28_16.11.2)
gitlab-ctl reconfigure
gitlab-ctl restart
'

注意:恢复必须使用相同或兼容版本(通常"同一小版本"最保险)。


关键注意事项(无论用 A 还是 B)

  1. 版本一致:先确认 A 上镜像 tag,再在 B 上用同一 tag 启动。避免"latest"自动升级导致恢复失败。

  2. 停机窗口:为避免数据写入丢失,最终迁移前要停容器再做最后一次 rsync/备份。

  3. 权限与 SELinux:拷贝要保留权限/属主(前文参数已包含)。如果 B 开了 SELinux,必要时:

    bash 复制代码
    # 例如在基于 RHEL 的系统
    sudo chcon -R -t container_file_t /home/liuguokai/docker/data/gitlab
  4. 端口与防火墙:B 上放行你映射的 80→5004 和 22→5005(SSH for Git over SSH),以及域名解析。

  5. external_url :地址/端口变动后,记得更新 /etc/gitlab/gitlab.rbexternal_urlgitlab-ctl reconfigure

  6. Runner 与 CI/CD:注册 token、变量都在 DB 里,随数据一起迁移。Runner 机器本身不迁移,需要它们重新连到新的 URL/IP(通常无需重新注册,取决于网络与证书变化)。

  7. 证书 :若用自签或自管证书,证书/私钥通常位于 /etc/gitlab/ssl/var/opt/gitlab/gitlab-rails/etc,随卷一起带走即可。


迁移后自检清单

  • Web 首页可打开,登录正常
  • 项目仓库能 git clone/push(HTTP 和 SSH)
  • CI Pipeline 能触发、Runner 正常执行
  • 容器日志无报错:docker logs -f gitlab
  • 备份目录自动轮转正常(如果你有设置)

如果你告诉我 A 上的具体镜像 tag 、B 上系统与目录 、以及新外网访问方式(是否换域名/端口/HTTPS),我可以把上述命令替换成你的实际值,给你一版"复制即用"的脚本。


明白了:B 机用的是 root 权限安装的新版本 Docker,账号是 dev,而且你可以把 GitLab 镜像以 tar 方式 docker load 。下面给你一套从 A → B的完整步骤(含"镜像 tar 迁移"与"应用备份恢复"两块)。按顺序执行即可。


在服务器 A(rootless 环境)

容器内路径 + docker cp 绕过宿主机卷权限问题。

1) 确认镜像版本并导出镜像 tar

bash 复制代码
# 记下 GitLab 镜像 tag
docker inspect gitlab --format '{{.Config.Image}}'
# 假设输出:gitlab/gitlab-ce:16.11.2-ce.0
IMG_TAG="gitlab/gitlab-ce:16.11.2-ce.0"

# 保存镜像为 tar(给 B 机 docker load 用)
docker save -o ~/gitlab-ce-16.11.2-ce.0.tar ${IMG_TAG}

2) 暂停写入并做 GitLab 应用备份

bash 复制代码
docker exec -it gitlab bash -lc 'gitlab-ctl stop sidekiq && gitlab-ctl stop puma'
docker exec -t gitlab gitlab-backup create
docker exec -t gitlab bash -lc 'ls -lh /var/opt/gitlab/backups/'
# 记住备份文件名,比如:1724908800_2025_08_29_16.11.2_gitlab_backup.tar

3) 用 docker cp 拷出备份与关键配置

bash 复制代码
# 备份包
docker cp gitlab:/var/opt/gitlab/backups/1724908800_2025_08_29_16.11.2_gitlab_backup.tar ~/ 

# 必须的两个配置
docker cp gitlab:/etc/gitlab/gitlab.rb ~/ 
docker cp gitlab:/etc/gitlab/gitlab-secrets.json ~/

# 如启用 HTTPS,连同证书拷出(如存在)
docker cp -a gitlab:/etc/gitlab/ssl ~/ssl

# 如本地启用 Container Registry(非对象存储),一并打包:
docker exec -it gitlab bash -lc 'if [ -d /var/opt/gitlab/registry ]; then tar -C /var/opt/gitlab -cpf /tmp/registry.tar registry; fi'
docker cp gitlab:/tmp/registry.tar ~/ 2>/dev/null || true

4) 传到 B

bash 复制代码
scp ~/gitlab-ce-16.11.2-ce.0.tar dev@B:/home/dev/
scp ~/*gitlab_backup.tar dev@B:/home/dev/
scp ~/gitlab.rb ~/gitlab-secrets.json dev@B:/home/dev/
[ -d ~/ssl ] && scp -r ~/ssl dev@B:/home/dev/
[ -f ~/registry.tar ] && scp ~/registry.tar dev@B:/home/dev/

(可选)恢复 A 上的服务:

bash 复制代码
docker exec -it gitlab bash -lc 'gitlab-ctl start puma && gitlab-ctl start sidekiq'

在服务器 B(rootful Docker,用户 dev)

0) 让 dev 能用 docker(如尚未做)

bash 复制代码
sudo usermod -aG docker dev
# 重新登录 shell(或 newgrp docker)后再继续

1) 准备目录 & 载入镜像 tar

bash 复制代码
BASE="/home/dev/docker/data/gitlab"
mkdir -p ${BASE}/{etc,log,opt,opt/backups}

# 加载镜像 tar(或直接 docker pull 同版本也可以)
docker load -i /home/dev/gitlab-ce-16.11.2-ce.0.tar

2) 启动"空" GitLab 容器(同版本)

bash 复制代码
IMG_TAG="gitlab/gitlab-ce:16.11.2-ce.0"
docker run -itd \
 -p 5004:80 \
 -p 5005:22 \
 -v ${BASE}/etc:/etc/gitlab \
 -v ${BASE}/log:/var/log/gitlab \
 -v ${BASE}/opt:/var/opt/gitlab \
 --restart always \
 --privileged=true \
 --name gitlab \
 --shm-size 1g \
 ${IMG_TAG}

# 等 1~2 分钟让它初始化目录结构(可跟日志观察)
docker logs -f gitlab | sed -n '1,120p'

3) 放入 A 的备份与配置(必要时先编辑 external_url)

bash 复制代码
# 放备份
mv /home/dev/*gitlab_backup.tar ${BASE}/opt/backups/

# 放配置与密钥(覆盖空实例的文件)
mv /home/dev/gitlab.rb ${BASE}/etc/
mv /home/dev/gitlab-secrets.json ${BASE}/etc/

# 如有证书
[ -d /home/dev/ssl ] && mv /home/dev/ssl ${BASE}/etc/

# 如有 Registry 数据(本地存储)
[ -f /home/dev/registry.tar ] && tar -C ${BASE}/opt -xpf /home/dev/registry.tar

# 如果 B 要改访问地址/端口/协议,请编辑 external_url
# 例如:
# sed -i 's|^external_url .*|external_url "http://<B的IP或域名>:5004"|' ${BASE}/etc/gitlab.rb

权限提示 :B 是 rootful Docker,卷中文件即使属于 dev 也没关系;容器内是 root,能正常读写。如需"更像原生",可:

bash 复制代码
sudo chown -R root:root ${BASE}/{etc,log,opt}

4) 恢复备份

bash 复制代码
# 停写
docker exec -it gitlab bash -lc 'gitlab-ctl stop sidekiq && gitlab-ctl stop puma'

# 取备份前缀(去掉结尾 _gitlab_backup.tar)
docker exec -it gitlab bash -lc 'ls -1 /var/opt/gitlab/backups'

# 假设前缀是 1724908800_2025_08_29_16.11.2
docker exec -it gitlab bash -lc 'yes yes | gitlab-backup restore BACKUP=1724908800_2025_08_29_16.11.2'

5) reconfigure & restart

bash 复制代码
docker exec -it gitlab bash -lc 'gitlab-ctl reconfigure && gitlab-ctl restart'

验证与收尾

bash 复制代码
# 日志
docker logs -f gitlab

# Web 访问
# http://<B的IP或域名>:5004  (如配置了 https 则用 https)

# Git over HTTP/SSH
git ls-remote http://<B>:5004/namespace/project.git
git ls-remote ssh://git@<B>:5005/namespace/project.git

# CI/CD & Runner
docker exec -it gitlab bash -lc 'gitlab-ctl status'
# 触发 pipeline;如更换了域名/证书,Runner 端按需更新 URL/证书信任

小贴士 / 踩坑预防

  • 镜像架构 要一致(A、B 同为 amd64 或同为 arm64);否则用 docker pull 官方多架构镜像更稳。
  • 保持版本一致(你已用镜像 tar;若用 pull 也请用相同 tag)。
  • Container Registry 如走对象存储则无需搬数据;如本地存储务必随同迁移。
  • 防火墙/安全组 放行 5004(HTTP/HTTPS 反代后视情况)和 5005(SSH for Git)。
  • external_url 变更 后一定要 gitlab-ctl reconfigure

如果你把在 A 机生成的备份文件名(完整或"前缀")贴出来,我可以把 B 机的 BACKUP= 命令替换成你的实际值,给你一版可直接粘贴执行的命令。

相关推荐
极小狐17 小时前
GitLab 18.3 正式发布,更新多项 DevOps、CI/CD 功能【一】
ci/cd·gitlab·devsecops·devops·极狐gitlab
阿提说说19 小时前
一个工程多Module的微服务项目,如何在GitLab中配置CI/CD
ci/cd·微服务·gitlab
q_q王19 小时前
linux安装gitlab详细教程,本地管理源代码
git·python·gitlab·代码
chenfengxiu19 小时前
Centos7安装gitlab
linux·运维·gitlab
北城笑笑4 天前
Git 9 ,.git/index.lock 文件冲突问题( .git/index.lock‘: File exists. )
前端·git·gitee·gitlab·github
streaker3035 天前
GitLab CI/CD 中实现前端增量 Lint(ESLint & Stylelint)实践
ci/cd·gitlab
柯南二号6 天前
【开发配置】GitLab CR(Code Review)规则配置清单
gitlab·代码复审
柯南二号6 天前
【开发配置】云服务器配置Gitlab服务
运维·服务器·gitlab
DevOps_node6 天前
docker-compose部署gitlab
gitlab·linux基础设施·linux中间件