首页 / 资讯中心 / 文章详情

Docker部署GitLab:PostgreSQL独立容器分离实践

Docker部署GitLab:PostgreSQL独立容器分离实践 ★ FEATURED ARTICLE
说一个我自己的经历。前两年团队内部只是跑一个单机版 GitLab当时图省事直接用官方一体化镜像所有组件——PostgreSQL、Redis、Gitaly、Sidekiq——全在一个容器里揉着。最开始几十人的小团队完全够用后来仓库数量和 CI 并发上来问题开始一个接一个备份恢复慢得离谱升级一次要停服半天PostgreSQL 单独想调参数又不敢乱动生怕把 GitLab 主进程带崩。后来我把整套服务拆成 Docker 部署 GitLab 独立 PostgreSQL 容器的方式也就是所谓的“数据库分离部署”。折腾完才体会到这个动作带来的收益远不止“看起来更专业”备份粒度、故障隔离、升级灵活性都完全不一样了。这篇就按我实际落地的过程聊聊为什么拆、怎么拆、拆完怎么管以及几个让我印象深刻的坑。1. 为什么要把 GitLab 的数据库拆出去踩坑之后的真实反思1.1 一体化部署的三大痛点先说清楚一体化镜像的使用体验。gitlab-ce 官方镜像内部用 Omnibus 包管理方式把所有组件都装在一个容器环境里。表面上docker run一条命令就能起来维护也确实简单但它有三个绕不开的问题。第一备份和恢复成了“全家桶”操作。一体化模式下GitLab 自带的备份工具会把仓库数据、数据库、配置一起打包。听起来自动化很好实际操作中你会发现备份时间随仓库数量增长飞快恢复时更麻烦——必须把整个备份包在“干净的同版本环境”里还原哪怕你只是想把数据库单独恢复到某个时间点也得起一套完整的 GitLab 环境。第二升级的连锁反应。GitLab 升级往往同时牵动 PostgreSQL 和 Redis 的版本。官方升级文档里有很多“必须先升到某个中间版本再跳到目标版本”的要求一体化部署每次升级都像拆炸弹。我有一次从 15.x 升到 16.x数据库自动迁移失败容器直接起不来最后只能回滚镜像折腾了整整半天。第三资源隔离和性能调优无从下手。一体化容器里所有进程共享同一份内存和 CPU你很难单独给 PostgreSQL 分配 shared_buffers也很难限制 Sidekiq 的内存占用。想监控数据库慢查询还得先进容器里手动装工具。说白了GitLab 和数据库被绑在一条船上谁出问题都一起沉。1.2 分离部署真正解决什么问题把数据库分离出去之后上面三个痛点基本都解决了。数据库容器可以独立启停、独立备份、独立升级——备份直接pg_dump拉一份 dump 就完事不会把所有仓库数据卷在一起GitLab 应用容器升级时数据库容器保持不动风险面缩小了一大截PostgreSQL 的参数可以随心调重启数据库容器也不影响 GitLab 容器本身的文件存储和服务状态应用会短暂连不上库但不会像一体化那样“连锅端”。分离部署还有一个隐性收益它为将来扩展铺好了路。GitLab 应用容器和数据库容器跑在同一台宿主机时你感觉不出太大差别但一旦仓库规模大到需要把数据库挪到独立服务器或云数据库实例上这套编排方式可以直接平移过去改个 host 指向就行。我后来帮某团队做高可用改造时就是拿这套分离方案当作基础版的雏形省了不少返工。2. 分离部署的整体架构与目录规划2.1 组件拓扑与关键端口我采用的拓扑很简单一台宿主机两个容器外加一个可选的 Nginx 反向代理或者直接用 GitLab 内置的 Nginx二选一别同时用在同一个端口上。核心组件结构如下GitLab 容器gitlab/gitlab-ce承担 Web、API、Git 存储、Sidekiq 后台任务、Gitaly 仓库访问。PostgreSQL 容器postgres:13.x 或 14.x专门承载 GitLab 的主数据库gitlabhq_production。其他依赖Redis 等我暂时没拆因为 Redis 相对轻量、迁移成本低初期分离数据库就足够解决主要痛点。如果你追求彻底拆分可以用同样的思路再加一个 Redis 容器配置方式类似但不在本文展开。端口规划上GitLab 容器对外只暴露 HTTPS 或 HTTP 端口我这里用 443映射宿主端口 8443 方便演示容器内部 5432 的 PostgreSQL 端口不映射到宿主机只在自定义 Docker 网络内互通。这样外部连不到数据库减少了暴露面。用 docker-compose 部署时两个容器会被自动放入同一个网络容器之间直接用服务名互相访问不需要知道宿主 IP。2.2 宿主目录规划与权限处理文件挂载是整个部署里最容易翻车的地方。GitLab 容器有三个目录必须持久化不光是家目录那样的/home/git那么简单容器内路径作用宿主路径示例/etc/gitlabgitlab.rb 配置、SSL 证书等/srv/gitlab/config/var/opt/gitlab仓库数据、对象存储、临时文件/srv/gitlab/data/var/log/gitlab日志/srv/gitlab/logs如果只挂载其中一个目录容器升级后很容易出现配置丢失或仓库数据“不见”的诡异现象。我最初只挂了/etc/gitlab和/var/opt/gitlab日志目录没管后来排查问题想查日志发现容器里一重启就清空了非常被动。权限上特别提醒GitLab 容器内部进程以 UID 998 或 1000 运行不同镜像版本可能不同Debian 系的 gitlab-ce 通常为 998宿主机目录如果权限不对容器启动时会疯狂报 permission denied。我的做法是提前创建目录然后chown -R 998:998交给容器使用比在容器里不断修改权限省心。数据库这边PostgreSQL 容器默认以 postgres 用户UID 999运行数据目录我单独给 UID 999 所有权避免两个容器的权限冲突。2.3 版本兼容性选择版本选型是分离部署的重中之重这里最容易踩“看着都能跑结果迁移失败”的坑。GitLab 对 PostgreSQL 的版本有明确要求不是随便拉一个最新版的 postgres 镜像就行。以我写这篇文章时的经验为准GitLab 15.x 系列官方支持 PostgreSQL 13 和 14GitLab 15.7 之后默认新装环境用 14。GitLab 16.x 系列支持 PostgreSQL 14 和 15官方推荐 14对 15 的支持也在逐渐完善。如果你选的 PostgreSQL 大版本高于 GitLab 支持的最高版本GitLab 初次reconfigure时可能能建库建表但后续某些迁移脚本执行时会因为 SQL 语法或权限模型差异直接失败。另一个方向也要注意如果 GitLab 版本太新而你的 PostgreSQL 版本太旧比如 GitLab 16 配 PG 12同样会遇到兼容性问题。安全做法是先确认你要安装的 GitLab 版本再查官方支持的数据库版本矩阵然后选匹配的 postgres 镜像。不要盲目追求“数据库越新越好”。我自己当前用的是 GitLab 16.x PostgreSQL 14这套组合相对稳很多线上团队也都是这个搭配。PostgreSQL 15 其实也可以用但如果你后面要参考网上旧的备份恢复脚本14 的社区资料更丰富遇到问题更容易搜到答案。3. docker-compose 编排一份可直接落地的配置3.1 数据库容器配置详解直接上一份我调好的 docker-compose.yml这段配置可以让两个容器以服务名互相发现避免手动建网络的麻烦。version: 3.8 services: gitlab-db: image: postgres:14.10 container_name: gitlab-db restart: unless-stopped environment: POSTGRES_USER: gitlab POSTGRES_PASSWORD: YourStrongDBPassword POSTGRES_DB: gitlabhq_production TZ: Asia/Shanghai volumes: - /srv/gitlab-db/data:/var/lib/postgresql/data networks: - gitlab-net healthcheck: test: [CMD-SHELL, pg_isready -U gitlab -d gitlabhq_production] interval: 10s timeout: 5s retries: 5 start_period: 10s shm_size: 1g重点解释几个容易被忽略的点。POSTGRES_DB我直接设成gitlabhq_production。PostgreSQL 官方镜像在首次初始化时会自动创建一个与POSTGRES_USER同名的数据库也会创建一个POSTGRES_DB指定的数据库。如果这里不显式指定GitLab 初始化时可能会因为找不到数据库而报错所以一开始就建好最省事。TZ一定要设置。GitLab 写入的日志时间默认是 UTC你宿主机是北京时间数据库容器也是 UTC结果看 GitLab 界面里的活动时间总是差了 8 小时。容器层面设置时区能保证数据库会话的now()结果和业务预期一致。healthcheck不是为了好看。GitLab 容器启动后要连数据库如果数据库还没就绪GitLab 重试一段时间后会放弃并报错。用 healthcheck 可以让 GitLab 容器在数据库真正就绪后才启动我从一开始就加了这段后面几乎没有遇到过“一方没起来另一方疯狂报错”的问题。注意pg_isready命令里必须带上-U gitlab否则它默认用当前系统用户名执行可能探测结果不准确。shm_size: 1g是给 PostgreSQL 的共享内存。PostgreSQL 的并行查询和 WAL 处理会用到/dev/shm容器默认只有 64MB高并发下容易报 “could not resize shared memory segment”。加这个参数后数据库容器能更从容地处理 GitLab 的并发写入。3.2 GitLab 容器配置详解GitLab 容器这侧的关键环境变量如下gitlab: image: gitlab/gitlab-ce:16.x.x-ce.0 container_name: gitlab restart: unless-stopped depends_on: gitlab-db: condition: service_healthy environment: GITLAB_OMNIBUS_CONFIG: | external_url http://gitlab.example.com postgresql[enabled] false gitlab_rails[db_host] gitlab-db gitlab_rails[db_port] 5432 gitlab_rails[db_username] gitlab gitlab_rails[db_password] YourStrongDBPassword gitlab_rails[db_database] gitlabhq_production gitlab_rails[db_sslmode] disable prometheus_monitoring[enable] false gitlab_rails[time_zone] Asia/Shanghai puma[worker_processes] 2 sidekiq[max_concurrency] 5 TZ: Asia/Shanghai ports: - 8443:443 - 8080:80 - 2222:22 volumes: - /srv/gitlab/config:/etc/gitlab - /srv/gitlab/data:/var/opt/gitlab - /srv/gitlab/logs:/var/log/gitlab shm_size: 2g networks: - gitlab-net networks: gitlab-net: driver: bridge最重要的三行是postgresql[enabled] false、gitlab_rails[db_host] gitlab-db和gitlab_rails[db_password]。postgresql[enabled] false告诉 Omnibus 不要内置并启动 PostgreSQL 服务而是使用外部数据库db_host指向数据库容器服务名gitlab-db因为同网络内容器可以用服务名互相解析密码必须和数据库容器里的POSTGRES_PASSWORD一致。prometheus_monitoring[enable] false是我建议加的。一体化镜像默认会拉起一堆监控采集器包括 node_exporter 和 postgres_exporter。既然数据库已经分离postgres_exporter 在没有本地数据库时意义不大禁用后能明显降低内存占用。GitLab 本身自带的基础监控页面不受影响。Puma worker 数和 Sidekiq 并发数我给了保守值。如果宿主机内存只有 8GB不建议调大。你可以在/etc/gitlab/gitlab.rb里改这些值但因为容器是用环境变量注入配置的重新docker compose up -d时会被环境变量覆盖所以直接写在这里最省事。端口映射里把容器的 22 映射到宿主 2222是因为 Git 原生 SSH 协议还需要保留。如果宿主机本身上面已经跑了别的 SSH 服务22 会被占用映射到一个高位端口是常见处理方式。使用者在 Git 地址里就该写成ssh://githost:2222/group/repo.git这一点后面一定要同步告诉团队成员否则他们会来问你“为什么 clone 不了”。3.3 首次启动与初始化验证配置写好后执行命令docker compose up -d首次启动时PostgreSQL 容器会快速完成初始化。GitLab 容器则不同它启动后要经历一个漫长的reconfigure过程里面包括生成配置文件、初始化数据库 schema、启用各项服务等步骤。这个过程根据机器性能可能需要 3 到 10 分钟甚至更久。第一次启动时我建议打开日志观察进度docker logs -f gitlab看到类似gitlab Reconfigured!或者nginx: configuration ... test is successful这样的字样就说明初始化基本完成了。此时访问你配置的external_url应该能看到 GitLab 首次设置的页面要求你设置 root 密码。验证数据库是不是真的连到了外部容器我推荐两种方式。第一种进入 GitLab 容器检查环境变量。如果你能看到DATABASE_HOSTgitlab-db说明 Omnibus 确实读到了外部数据库配置。第二种更直接在 GitLab 容器里执行gitlab-rails db:version或者gitlab-psql -c select version();。注意gitlab-psql这条命令只有在系统检测到外部数据库配置后才会生效如果它还尝试连接本地 socket说明你的db_host配置没有生效。我用gitlab-rails db:version验证过很多次正常情况下会输出一个 schema 版本号这说明 Rails 已经成功连接外部 PostgreSQL 并完成了迁移。4. 数据库初始化与 GitLab 连接的关键细节4.1 数据库账号的权限边界GitLab 首次连接外部数据库时需要创建一个叫gitlabhq_production的库并执行大量迁移脚本。为此数据库账号必须具备CREATEDB权限。官方文档给的指引是创建一个普通登录账号并授予 CREATEDB但并不需要SUPERUSER权限。如果你给的是一个超级用户部署时确实省事但安全隐患较大——一旦 GitLab 的数据库凭据泄露攻击者能直接控制整个数据库实例。分离部署本来就是为了边界更清晰凭什么把钥匙全部交出去最小权限原则在这里同样适用。我习惯这样创建数据库角色如果你直接用官方镜像的环境变量初始化它创建的gitlab用户已经自带 CREATEDB就不需要额外操作docker exec -it gitlab-db psql -U postgres -c CREATE ROLE gitlab LOGIN PASSWORD YourStrongDBPassword CREATEDB;同时建议限制连接来源。pg_hba.conf里默认允许所有网段连接你可以在 postgres 镜像的启动参数中增加-c listen_addresses*并依靠 Docker 网络隔离来保证只有同网络的 GitLab 容器能访问数据库实例。如果你的 GitLab 容器被映射到了公网数据库端口一定不要同时映射到宿主机否则等于裸奔。4.2 GitLab 依靠哪些环境变量感知外部数据库很多人部署失败是因为把数据库配置写进了 gitlab.rb 但没让 Omnibus 重新加载或者配置写在容器环境变量之外导致启动时不起作用。我从实际调试中总结核心机制是GITLAB_OMNIBUS_CONFIG这个环境变量的内容会在容器启动时被追加进/etc/gitlab/gitlab.rb然后执行gitlab-ctl reconfigure。所以你所有要覆盖的配置项都必须出现在这个环境变量里而不能只写在挂载出来的 gitlab.rb 文件中——因为容器每次启动会用环境变量的内容重新生成配置。具体到数据库这块需要覆盖的配置项如下配置项作用示例值postgresql[enabled]是否使用内置 Postgresfalsegitlab_rails[db_host]数据库主机地址gitlab-dbgitlab_rails[db_port]数据库端口5432gitlab_rails[db_username]数据库用户名gitlabgitlab_rails[db_password]数据库密码YourStrongDBPasswordgitlab_rails[db_database]数据库名gitlabhq_productiongitlab_rails[db_sslmode]数据库连接 SSL 模式disable其中db_sslmode容易忽略。如果 PostgreSQL 容器没有启用 SSL而 GitLab 默认用prefer模式连接部分驱动在特定环境下会尝试 SSL 握手并失败。我在排查 GitLab 日志时遇到过几次SSL error: sslmode value prefer invalid的报错虽然通过设置sslmode为disable后问题消失但它提醒我连接参数最好显式声明不要依赖默认值。4.3 时区、字符集与网络问题的处理时区问题我在前文提过这里再展开一下操作细节。除了数据库容器的TZ环境变量GitLab 容器内部还需要设置gitlab_rails[time_zone]这个值同时影响 GitLab Web 界面中显示的时间、Sidekiq 定时任务的调度以及 CI 运行日志里的时间戳。字符集方面PostgreSQL 官方镜像默认使用UTF8这刚好是 GitLab 要求的字符集。但要注意你在POSTGRES_DB初始化时如果指定了名称PostgreSQL 会用template1的字符集创建数据库只要template1保持 UTF8一般没问题。我见过有人为了“性能”手动把数据库字符集改成SQL_ASCII到后面中文仓库名或者 CI 日志里出现乱码完全得不偿失。网络问题最常见的表现是容器能互相 ping 通但 GitLab 连不上数据库。这种情况先确认两个容器是不是在同一个gitlab-net网络里。用docker network inspect gitlab-net查看连接的容器列表别凭感觉以为 compose 同一文件就会自动同网络——如果你手动创建过同名网络或者 compose 项目名做了特殊处理网络隔离会比你想象的更严格。还有一个容易栽的点如果宿主机上已经装了一个 PostgreSQL 服务占用了 5432 端口而你又尝试把数据库容器端口映射到宿主 5432会报端口冲突。既然采用容器网络互访数据库容器完全不需要映射端口到宿主机少一个端口映射就少一种冲突可能。5. 备份与恢复分离部署后最容易搞错的流程5.1 数据库备份的正确姿势分离部署后最让我后怕的是很多人仍然用 GitLab 自带的备份命令直接备份。不是说自带备份没用而是它的备份逻辑会把数据库 dump 和仓库数据一起打包你如果只需要恢复数据库到某个时间点这个“全家桶”反而笨重。数据库层面我推荐直接用 PostgreSQL 的逻辑备份工具。进入数据库容器执行docker exec gitlab-db pg_dump -U gitlab -d gitlabhq_production -F c -f /tmp/gitlab_$(date %F).dump-F c表示自定义格式支持以后用 pg_restore 做选择性恢复比纯 SQL dump 更灵活。如果你担心 dump 过程中 GitLab 还在写入导致数据不一致可以加--lock-wait-timeout30s让 pg_dump 等待短暂锁释放或者直接在psql里执行BEGIN; LOCK TABLE ... IN SHARE MODE;再 dump但不推荐在业务高峰期做这个操作。备份文件在容器内生成后需要复制到宿主机或对象存储docker cp gitlab-db:/tmp/gitlab_20250101.dump /srv/backups/gitlab-db/仓库数据的备份仍然用 GitLab 自带的备份命令但注意它会只备份仓库和配置数据库部分因为检测到外部数据库配置会通过pg_dump连接外部数据库执行 dump。所以你在跑gitlab-backup create时一定要保持数据库容器在线否则这一步会失败。5.2 灾难恢复的完整顺序恢复流程的顺序比命令本身更重要。我见过有人先把 GitLab 容器启动再恢复数据库结果 GitLab 启动时检测到 schema 版本对不上自动执行了一些迁移操作把数据库结构搞得更乱了。正确的恢复顺序是停掉 GitLab 应用容器让它不要产生新的写入和迁移docker compose stop gitlab恢复数据库 dump先删掉或者重命名旧的gitlabhq_production库再用pg_restore导入备份。注意导入前确认目标库字符集和编码一致。如果还要恢复仓库数据用 GitLab 的gitlab-backup restore命令完成它会读取备份目录里的仓库数据包。最后启动 GitLab 容器docker compose start gitlab为什么必须先恢复数据库再启动应用因为 GitLab 启动时会检查数据库 schema migration 状态如果库里没有数据空库或数据不完整它会尝试执行一部分迁移并写坏状态。先恢复完整数据库再启动应用应用会认为迁移已经完成不会做多余动作。pg_restore的典型用法docker exec -i gitlab-db pg_restore -U gitlab -d gitlabhq_production --clean --if-exists /tmp/gitlab_20250101.dump--clean会在导入前 drop 已存在的对象避免重复创建报错--if-exists配合使用会更温和一些。导入过程可能提示一些错误但只要不是中断性的通常不影响最终结果。5.3 定时备份脚本参考定时备份是运维的基本盘不能靠手敲命令。我分享一个简单但完整的脚本方案放在宿主机 crontab 里执行#!/bin/bash set -e BACKUP_DIR/srv/backups/gitlab-db DATE$(date %F) mkdir -p $BACKUP_DIR docker exec gitlab-db pg_dump -U gitlab -d gitlabhq_production -F c -f /tmp/gitlab_${DATE}.dump docker cp gitlab-db:/tmp/gitlab_${DATE}.dump ${BACKUP_DIR}/ docker exec gitlab-db rm -f /tmp/gitlab_${DATE}.dump # 保留最近 14 天的数据库备份 find $BACKUP_DIR -name *.dump -mtime 14 -exec rm -f {} \;crontab 配置为每天凌晨 2 点执行0 2 * * * /usr/local/bin/backup_gitlab_db.sh /var/log/gitlab_backup.log 21这个脚本没有覆盖 GitLab 仓库数据备份仓库数据建议用gitlab-backup create再配合对象存储上传。如果你只有数据库备份而没有仓库数据备份仓库直接丢失的灾难场景还是救不回来。实际项目中我把两者分成了两个 cron 任务仓库数据每 6 小时一次数据库每日一次这样既平衡了备份窗口压力又能容忍一天之内的数据丢失。6. 升级、迁移与常见故障排查记录6.1 GitLab 版本升级的正确步骤分离部署后升级 GitLab 的痛点会不会消失只能说显著缓解但没有完全消失。应用容器升级后如果新版本包含数据库迁移脚本它依然会连到外部数据库执行迁移。所以升级流程还是要有章法。我的标准流程是先备份数据库docker exec gitlab-db pg_dump ...按前一节脚本即可。备份 GitLab 配置目录tar cvf /srv/backups/gitlab-config.tgz /srv/gitlab/config修改 docker-compose.yml 中的镜像版本号然后docker compose pull gitlab拉取新镜像。执行docker compose up -d gitlab这会重建容器但保留原有卷。观察日志等待reconfigure完成和数据库迁移自动执行。需要注意的是 GitLab 官方不建议跨大版本跳级升级。比如从 15.x 直接升到 16.x少数情况下可以但从 14.x 直接升到 16.x迁移脚本可能报错。稳妥的做法是逐个大版本升级14 → 15 → 16每个大版本内选择最新补丁版。升级到新版本后如果gitlab-rake db:migrate出现异常第一反应应该是查看错误日志涉及哪个表或 SQL而不是盲目重试。数据库容器的 PostgreSQL 版本在 GitLab 升级时一般不需要跟着动尤其是从 15 升 16 这种跨度官方可能要求 PG 13 或 14 已满足要求。如果某次 GitLab 大版本升级后要求更高版本 PG再单独规划数据库容器升级步骤是pg_dump备份 → 创建新版本 PG 容器 → 导入 → 修改 GitLab 的 db_host 指向新容器 → 重启 GitLab。这个过程里注意不要同时升级应用和数据库一次只动一个变量出问题好定位。6.2 故障案例排查从现象到根因记录几个我在分离部署前后实际踩过的坑每个都有完整的排查链路希望对你有参考价值。案例一GitLab 启动后 502 错误现象GitLab 容器一直在重启页面打不开日志大量刷connection to server at gitlab-db failed: connection refused。排查过程先检查数据库容器是否正常运行docker ps显示它确实活着说明进程没挂。再检查健康状态docker inspect --format{{.State.Health.Status}} gitlab-db发现是unhealthy。手动在宿主机执行docker exec gitlab-db pg_isready -U gitlab -d gitlabhq_production返回/var/run/postgresql:5432 - no response。进一步看数据库日志docker logs gitlab-db发现could not bind to address ... Permission denied。原来我把/srv/gitlab-db/data目录的属主设成了宿主机当前用户PostgreSQL 容器内 postgres 用户无法在该目录创建 socket 文件。改成chown -R 999:999 /srv/gitlab-db/data并重启数据库容器后健康检查变绿GitLab 也顺利起来了。案例二数据库连上了但 GitLab 一直报表不存在现象GitLab 能连接数据库日志却出现relation users does not exist之类的错误。排查过程第一反应是数据库迁移没跑完进入 GitLab 容器执行gitlab-rake db:migrate:status发现大部分迁移都是 down 状态。再检查数据库列表docker exec gitlab-db psql -U gitlab -l发现连接的是postgres数据库而不是gitlabhq_production。根因是 docker-compose 里数据库容器的POSTGRES_DB没设置导致gitlabhq_production没有被初始化GitLab 连接失败后回退到了默认库。解决办法是补上POSTGRES_DB: gitlabhq_production重建数据库容器并重新初始化。这种问题在配置检查阶段很难发现正因为如此POSTGRES_DB一定要在第一次启动前就配好别指望事后改环境变量就能自动建库。案例三恢复数据库后 GitLab 报数据库版本不兼容现象用旧版本 PG 的 dump 恢复到新版本 PG 容器后GitLab 容器日志提示PostgreSQL version 15 is not supported by this GitLab version。排查过程这属于版本选型没提前对齐。我刚开始图省事直接拉了 postgres:16GitLab 16 虽然理论上兼容 15但对 16 的支持还不够好官方文档明确列了支持矩阵。根因不是恢复流程的问题而是容器选型一开始就错了。解决方案重新创建一个 PostgreSQL 14 容器重新导入 dump。这个过程中的教训是分离部署后数据库容器是自己的升级数据库前必须先看 GitLab 官方支持矩阵不能用“反正 PG 向上兼容”的思维。6.3 后续扩展思路从单机到多节点分离部署之后再想往更完整的架构演进思路会变得很顺。数据库已经独立成容器下一步最自然的方向就是把数据库容器挪到独立宿主机或者干脆替换成云厂商的托管数据库服务。GitLab 那边只需要改db_host配置并确保网络可达应用容器完全不需要动这个平滑度是一体化部署给不了的。如果你对容灾要求更高还可以给 PostgreSQL 容器增加流复制备库。GitLab 官方支持配置多个数据库主机地址但更常见的做法是在数据库层做流复制。容器内做流复制需要额外配置primary_conninfo和pg_hba.conf我不会在这一篇里展开讲但它完全建立在“数据库已被独立出来”的前提之上。我建议初学者先把这篇里的单机分离方案跑稳两三个月的运行数据能证明备份、恢复、升级流程都顺畅了再考虑更复杂的多节点架构。技术上没有一步登天的捷径每一步都验证扎实后面才能少返工。最后的实际感受分离部署 GitLab 这件事投入的时间主要在“头一次踩坑”真正跑顺之后日常维护负担不升反降。最明显的体感变化是以前升级 GitLab 恨不得专门留一个下午现在只要数据库备份没问题应用容器升级基本是十分钟内的事以前数据库出问题只能悔不当初现在直接单独处理数据库容器不必陪它“全损”。如果你正准备新装 GitLab我建议不管你团队规模多小都直接从分离部署开始。表面上多了一个容器、多了一份 docker-compose 配置但换来的操作自由度完全值回票价。数据库分离这个习惯一旦养成了后面无论做大做强还是故障应急你都比别人从容得多。
阅读完成 · 觉得有帮助?
咨询建站