GitLab (Docker) 常用命令及解决方案清单

GitLab (Docker) 常用命令及解决方案清单

本清单基于解决 GitLab CE 18.4.0 Docker 容器中 PostgreSQL 数据损坏、数据恢复、外部数据库迁移等实际问题的经验整理。


一、数据库损坏修复

1. 定位损坏对象

sql 复制代码
-- 进入数据库控制台
docker exec -it <容器名> gitlab-psql

-- 根据 relfilenode 查询表名
SELECT c.oid, n.nspname AS schema, c.relname,
       CASE c.relkind WHEN 'r' THEN 'table' WHEN 'i' THEN 'index' END AS type
FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relfilenode = 17102;   -- 替换为实际数字

2. 尝试跳过损坏页面(需重启 PostgreSQL)

bash 复制代码
# 方法一:修改 postgresql.conf(宿主机路径)
echo "ignore_invalid_pages = on" >> /宿主机数据目录/postgresql/data/postgresql.conf
docker restart <容器名>

# 方法二:通过 gitlab.rb 永久配置(推荐)
echo "postgresql['custom_config'] = { 'ignore_invalid_pages' => 'on' }" >> /etc/gitlab/gitlab.rb
docker exec -it <容器名> gitlab-ctl reconfigure
docker restart <容器名>

# 验证是否生效
docker exec -it <容器名> gitlab-psql -c "SHOW ignore_invalid_pages;"

3. 抢救损坏表的数据

sql 复制代码
-- 创建备份表(会跳过损坏页面,若失败则用逐行插入)
CREATE TABLE namespaces_backup AS TABLE namespaces;

-- 若报错,改用逐行插入
CREATE TABLE namespaces_backup (LIKE namespaces INCLUDING ALL);
DO $$
DECLARE r RECORD;
BEGIN
    FOR r IN SELECT * FROM namespaces LOOP
        BEGIN
            INSERT INTO namespaces_backup VALUES (r.*);
        EXCEPTION WHEN OTHERS THEN
            RAISE NOTICE 'Skipping row: %', SQLERRM;
        END;
    END LOOP;
END $$;

-- 替换原表
DROP TABLE namespaces;
ALTER TABLE namespaces_backup RENAME TO namespaces;

4. 单用户模式强制修复(绕过 Omnibus)

bash 复制代码
# 停止 GitLab 进程,手动启动 PostgreSQL
docker exec -it <容器名> gitlab-ctl stop
docker exec -it <容器名> rm -f /var/opt/gitlab/postgresql/data/postmaster.pid
docker exec -it <容器名> su - gitlab-psql -c "/opt/gitlab/embedded/bin/postgres --single -c ignore_invalid_pages=on -D /var/opt/gitlab/postgresql/data template1"

二、数据库完全重置(不保留数据)

bash 复制代码
# 进入容器
docker exec -it <容器名> /bin/bash

# 停止非数据库服务
gitlab-ctl stop sidekiq puma nginx

# 强制重置(跳过保护)
DISABLE_DATABASE_ENVIRONMENT_CHECK=1 gitlab-rails db:drop db:create db:migrate

# 手动创建基础数据(若 db:seed 失败)
gitlab-rails runner "ApplicationSetting.create_from_defaults"
gitlab-rails runner "User.create(username: 'root', email: 'admin@example.com', name: 'Administrator', admin: true, password: 'your_password', password_confirmation: 'your_password')"

# 重新配置并启动
gitlab-ctl reconfigure
gitlab-ctl restart

三、用户管理(当登录失效)

1. 重置 root 密码

bash 复制代码
# 方法一:使用 rake 任务
docker exec -it <容器名> gitlab-rake "gitlab:password:reset[root]"

# 方法二:通过 rails console
docker exec -it <容器名> gitlab-rails console
user = User.find_by_username('root')
user.password = 'new_password'
user.password_confirmation = 'new_password'
user.save!
exit

2. 创建新管理员用户

ruby 复制代码
# rails console 中执行
user = User.new(
  username: 'new_admin', email: 'admin@example.com', name: 'Admin',
  password: 'password', password_confirmation: 'password',
  admin: true, projects_limit: 10000
)
user.skip_confirmation!
user.save!

四、数据备份与恢复

1. 备份整个数据目录(宿主机)

bash 复制代码
cp -r /volume1/dockerdata/gitlab /volume1/backup/gitlab_$(date +%Y%m%d)

2. 备份代码仓库(仅仓库,不含数据库)

bash 复制代码
docker exec -it <容器名> tar -czf /tmp/repositories.tar.gz -C /var/opt/gitlab/git-data/repositories .
docker cp <容器名>:/tmp/repositories.tar.gz /volume1/backup/

3. 备份 GitLab 配置和密钥

bash 复制代码
docker cp <容器名>:/etc/gitlab/gitlab.rb /volume1/backup/
docker cp <容器名>:/etc/gitlab/gitlab-secrets.json /volume1/backup/
docker cp <容器名>:/etc/gitlab/ssh_host_* /volume1/backup/

4. 完整备份(官方工具)

bash 复制代码
docker exec -it <容器名> gitlab-backup create
# 备份文件位于 /var/opt/gitlab/backups/

5. 恢复备份

bash 复制代码
# 停止服务
docker exec -it <容器名> gitlab-ctl stop puma sidekiq
# 恢复(BACKUP=时间戳)
docker exec -it <容器名> gitlab-backup restore BACKUP=1734567890_2025_04_25_18.4.0
# 重启
docker exec -it <容器名> gitlab-ctl restart

6. 仅恢复仓库文件(放弃数据库)

bash 复制代码
# 清空现有仓库目录
docker exec -it <容器名> rm -rf /var/opt/gitlab/git-data/repositories/*
# 解压备份
docker cp /volume1/backup/repositories.tar.gz <容器名>:/tmp/
docker exec -it <容器名> tar -xzf /tmp/repositories.tar.gz -C /var/opt/gitlab/git-data/repositories/
docker exec -it <容器名> chown -R git:git /var/opt/gitlab/git-data/repositories

五、切换到外部 PostgreSQL 数据库

1. 在外部 PG 中创建数据库和用户

sql 复制代码
CREATE USER gitlab WITH PASSWORD 'your_password';
ALTER ROLE gitlab WITH SUPERUSER CREATEDB CREATEROLE REPLICATION;
CREATE DATABASE gitlabhq_production OWNER gitlab;

2. 导出内部数据(使用 Unix socket)

bash 复制代码
docker exec -it gitlab18.4.0 /opt/gitlab/embedded/bin/pg_dump \
  -h /var/opt/gitlab/postgresql -U gitlab -c -C -f /tmp/gitlabhq_production.sql gitlabhq_production
docker cp gitlab18.4.0:/tmp/gitlabhq_production.sql .

3. 导入到外部 PG

bash 复制代码
PGPASSWORD='your_password' psql -h 192.168.1.6 -p 15432 -U gitlab -f gitlabhq_production.sql postgres

4. 修改 GitLab 配置

ruby 复制代码
# 编辑 /etc/gitlab/gitlab.rb,追加:
postgresql['enable'] = false
gitlab_rails['db_host'] = '192.168.1.6'
gitlab_rails['db_port'] = 15432
gitlab_rails['db_username'] = 'gitlab'
gitlab_rails['db_password'] = 'your_password'
gitlab_rails['db_database'] = 'gitlabhq_production'

5. 重新配置并重启

bash 复制代码
docker exec -it <容器名> gitlab-ctl reconfigure
docker exec -it <容器名> gitlab-ctl restart

六、配置管理(避免修改被覆盖)

1. 正确的永久配置方法(通过 gitlab.rb)

bash 复制代码
# 进入容器
docker exec -it <容器名> /bin/bash
# 编辑主配置文件
editor /etc/gitlab/gitlab.rb
# 追加配置,例如:
postgresql['custom_config'] = { 'ignore_invalid_pages' => 'on' }
gitlab_rails['db_password'] = 'my_password'
# 应用配置
gitlab-ctl reconfigure

2. 查看当前生效的配置

bash 复制代码
docker exec -it <容器名> gitlab-rails runner "puts Gitlab::CurrentSettings.inspect"

七、日志维护

1. 安全清理日志(推荐)

bash 复制代码
# 手动触发 logrotate
docker exec -it <容器名> logrotate -f /etc/logrotate.d/gitlab

# 或配置自动轮转(在 gitlab.rb 中)
logging['logrotate_frequency'] = "daily"
logging['logrotate_rotate'] = 30
logging['logrotate_compress'] = "compress"
gitlab-ctl reconfigure

2. 查看实时日志

bash 复制代码
docker exec -it <容器名> gitlab-ctl tail           # 所有服务
docker exec -it <容器名> gitlab-ctl tail postgresql
docker exec -it <容器名> gitlab-ctl tail gitlab-rails

3. 清理 Docker 容器日志(宿主机)

bash 复制代码
truncate -s 0 /var/lib/docker/containers/*/*-json.log

八、容器与数据目录操作

1. 停止并删除容器(保留数据卷)

bash 复制代码
docker stop <容器名>
docker rm <容器名>

2. 使用旧数据卷启动新容器

bash 复制代码
docker run --detach \
  --name gitlab-new \
  --publish 3084:443 --publish 3022:80 --publish 3012:22 \
  --volume /volume1/dockerdata/gitlab/config:/etc/gitlab \
  --volume /volume1/dockerdata/gitlab/logs:/var/log/gitlab \
  --volume /volume1/dockerdata/gitlab/data:/var/opt/gitlab \
  docker.1ms.run/gitlab/gitlab-ce:18.4.0-ce.0

3. 进入容器执行命令

bash 复制代码
docker exec -it <容器名> /bin/bash
docker exec -it <容器名> gitlab-psql
docker exec -it <容器名> gitlab-rails console

九、常见错误及快速解决

错误信息 快速解决
connection to server on socket ".../.s.PGSQL.5432" failed 使用 gitlab-psql 或指定 -h /var/opt/gitlab/postgresql
permission denied to set parameter "ignore_invalid_pages" 通过 gitlab.rb 配置并执行 gitlab-ctl reconfigure
Validation failed: Namespace can't be blank 使用 Users::CreateService 创建用户,或先创建 root
gitlab-ctl stop 导致容器退出 不要停全部服务,只停需要的:gitlab-ctl stop sidekiq puma
pg_dump: connection refused 改用 Unix socket:-h /var/opt/gitlab/postgresql
FATAL: lock file "postmaster.pid" already exists rm -f /var/opt/gitlab/postgresql/data/postmaster.pid

十、终极恢复:放弃数据库只保代码

当数据库损坏无法修复时,按以下顺序操作:

  1. 备份当前仓库:tar -czf repos.tar.gz /var/opt/gitlab/git-data/repositories
  2. 停止并删除旧容器,彻底删除数据卷中的 postgresql 目录。
  3. 启动新容器,让 GitLab 自动初始化数据库。
  4. 导入仓库备份,修复权限。
  5. 登录 Web 界面,手动创建项目(路径必须与原项目一致),GitLab 会自动关联已有仓库。

此方案会丢失所有 issues、MR、用户权限等元数据,但代码仓库完整保留。


以上清单涵盖了本次排障过程中的主要命令和解决方案,可根据实际情况选用。

相关推荐
卧室小白1 小时前
K8S基础-控制器&deploy&pod回滚更新&service
docker·容器·kubernetes
许彰午1 小时前
零基础无文档啃读纯实操摸索学会Docker全过程
运维·docker·容器
江湖有缘1 小时前
零门槛搭建个人微社区:Docker部署 Paopao-ce 完整教程
运维·docker·容器
qq_356408661 小时前
GitLab 单机私有化部署文档(基于 Docker 环境)
docker·gitlab
皮皮蟹虾饺15 小时前
DNS协议指南:从报文格式到安全加密与 K8s 实战
安全·容器·kubernetes
千寻girling16 小时前
记录第一次学习 Docker
学习·docker·容器
迷糊小面包17 小时前
Docker Hadopp集群版部署搭建及常规问题解疑
运维·docker·容器
烁34718 小时前
Docker
运维·docker·容器
网络中的夜鹰19 小时前
轩辕镜像一键安装Docker和Docker Compose脚本
运维·docker·容器