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= 命令替换成你的实际值,给你一版可直接粘贴执行的命令。

相关推荐
明月心9521 天前
git remote add 用法
gitlab
only_Klein1 天前
jenkins流水线报错:Connection reset by peer
ci/cd·kubernetes·gitlab·jenkins·ssl
梁萌2 天前
docker部署gitlab和gitlab runner
docker·eureka·gitlab
johnnyAndCode2 天前
Idea 设置GitLab时使用账密,而不是token的配置方法
gitlab·idea
天外飞雨2 天前
Gitlab使用
gitlab
BUTCHER53 天前
GitLab SSH 密钥配置
运维·ssh·gitlab
明月心9523 天前
GitLab使用
gitlab
明月心9524 天前
gitlab pull requets
gitlab
BUTCHER54 天前
GitLab基本设置
gitlab
张小凡vip4 天前
Kubernetes---gitlab的ci/cd发布基于k8s的项目示例参考
ci/cd·kubernetes·gitlab