1. 为什么选择Docker部署代码管理平台
在团队协作开发中,代码管理平台是基础设施中的核心组件。传统物理机部署方式需要手动安装依赖、配置环境,不仅耗时费力,还存在"环境漂移"的风险。我在多个项目中尝试过不同部署方案后,发现Docker容器化部署具有明显优势:
- 环境一致性:容器镜像打包了所有运行时依赖,彻底解决"在我机器上能跑"的经典问题
- 快速部署:通过Docker Compose可以一键拉起全套服务,新成员 onboarding 时间从小时级降到分钟级
- 资源隔离:每个服务运行在独立容器中,避免端口冲突和依赖污染
- 版本控制:镜像版本与代码版本可以严格对应,方便回滚和追溯
GitLab作为全功能的DevOps平台,提供从代码托管到CI/CD的全套解决方案;而Gerrit则以严格的代码评审机制著称,特别适合需要精细权限控制的大型项目。将二者结合使用,既能享受GitLab的便捷性,又能通过Gerrit保证代码质量。
提示:生产环境部署建议使用Docker Swarm或Kubernetes集群,本文主要介绍单机部署方案作为入门。
2. 部署环境准备
2.1 硬件资源配置建议
根据我的经验,同时运行GitLab和Gerrit需要合理规划资源:
| 服务 | CPU核心 | 内存 | 磁盘空间 |
|---|---|---|---|
| GitLab | 4核+ | 8GB+ | 50GB+ |
| Gerrit | 2核+ | 4GB+ | 20GB+ |
| 总计 | 6核 | 12GB | 70GB |
实测发现GitLab特别吃内存,当内存不足时会出现502错误。如果资源有限,可以考虑:
- 调低Unicorn worker数量:修改
/etc/gitlab/gitlab.rb中的unicorn['worker_processes'] - 禁用不必要的服务:如Mattermost、Registry等
- 使用SSD硬盘提升IO性能
2.2 软件依赖安装
首先确保宿主机已安装最新版Docker和Docker Compose:
bash复制# Ubuntu示例
sudo apt-get update
sudo apt-get install -y docker.io docker-compose
sudo systemctl enable --now docker
验证安装:
bash复制docker --version # 应显示20.10+
docker-compose --version # 应显示1.29+
注意:避免使用
sudo直接运行docker命令,应将用户加入docker组:bash复制sudo usermod -aG docker $USER newgrp docker # 立即生效
3. GitLab容器化部署
3.1 使用官方镜像快速启动
GitLab官方提供了All-in-One的Docker镜像,包含所有组件:
bash复制docker run --detach \
--hostname gitlab.example.com \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:latest
关键参数说明:
--hostname:必须设置为最终访问的域名,否则CI/CD会报错--shm-size:解决Sidekiq内存不足问题- 三个volume分别挂载配置、日志和数据
首次启动需要3-5分钟初始化,通过docker logs -f gitlab查看进度。当看到GitLab configured and started表示启动完成。
3.2 关键配置调整
修改/srv/gitlab/config/gitlab.rb(容器内路径为/etc/gitlab/gitlab.rb):
ruby复制external_url 'http://gitlab.example.com' # 必须与--hostname一致
gitlab_rails['initial_root_password'] = 'your_secure_password'
gitlab_rails['time_zone'] = 'Asia/Shanghai'
gitlab_rails['gitlab_shell_ssh_port'] = 22 # 如果修改了宿主机SSH端口需调整
# 邮件配置(必须)
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.example.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "gitlab@example.com"
gitlab_rails['smtp_password'] = "smtp_password"
gitlab_rails['smtp_domain'] = "example.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
应用配置:
bash复制docker exec -it gitlab gitlab-ctl reconfigure
docker restart gitlab
3.3 常见问题排查
问题1:访问出现502错误
- 检查内存是否不足:
docker stats gitlab - 查看日志:
docker logs --tail 100 gitlab - 尝试增加SWAP空间
问题2:SSH克隆失败
- 确认
gitlab_rails['gitlab_shell_ssh_port']与宿主机映射端口一致 - 检查防火墙规则:
sudo ufw allow 22/tcp
问题3:邮件发送失败
- 测试SMTP配置:
docker exec -it gitlab gitlab-rails console,然后执行:ruby复制Notify.test_email('recipient@example.com', 'Test', 'Test').deliver_now
4. Gerrit容器化部署
4.1 选择适合的镜像版本
Gerrit官方镜像有两个主要版本:
gerritcodereview/gerrit:标准版gerritcodereview/gerrit-ci:包含CI功能
建议使用固定版本而非latest标签:
bash复制docker pull gerritcodereview/gerrit:3.6.0
4.2 使用Docker Compose编排
创建docker-compose-gerrit.yml:
yaml复制version: '3'
services:
gerrit:
image: gerritcodereview/gerrit:3.6.0
container_name: gerrit
restart: always
ports:
- "29418:29418"
- "8080:8080"
volumes:
- /srv/gerrit/etc:/var/gerrit/etc
- /srv/gerrit/git:/var/gerrit/git
- /srv/gerrit/index:/var/gerrit/index
- /srv/gerrit/cache:/var/gerrit/cache
environment:
- CANONICAL_WEB_URL=http://gerrit.example.com
- AUTH_TYPE=DEVELOPMENT_BECOME_ANY_ACCOUNT # 测试用,生产环境需改为LDAP或OAUTH
启动服务:
bash复制docker-compose -f docker-compose-gerrit.yml up -d
4.3 初始化配置
首次访问http://localhost:8080会进入初始化向导:
- 选择认证方式(生产环境推荐LDAP)
- 设置管理员账号
- 配置邮件服务器
- 创建第一个项目
关键配置文件位于/srv/gerrit/etc/gerrit.config,建议修改:
ini复制[gerrit]
basePath = git
serverId = gerrit-01
canonicalWebUrl = http://gerrit.example.com
[auth]
type = LDAP
gitBasicAuth = true
[ldap]
server = ldap://ldap.example.com
username = cn=admin,dc=example,dc=com
password = ldap_password
accountBase = ou=people,dc=example,dc=com
groupBase = ou=groups,dc=example,dc=com
重启生效:
bash复制docker-compose -f docker-compose-gerrit.yml restart
5. 集成GitLab与Gerrit工作流
5.1 典型协作流程设计
结合两个工具的优势,我推荐以下工作流:
-
开发阶段:使用GitLab进行日常代码托管和CI/CD
- 功能分支开发
- Merge Request进行团队协作
- 自动化测试和构建
-
代码审核阶段:推送到Gerrit进行严格评审
- 开发者通过
git push origin HEAD:refs/for/master提交评审 - 评审人通过+1/+2投票
- 满足条件后自动合并
- 开发者通过
-
发布阶段:通过GitLab Pipeline完成部署
5.2 配置Gerrit Trigger插件
在GitLab Runner的config.toml中添加:
toml复制[[runners]]
name = "gerrit-sync"
url = "http://gitlab.example.com"
token = "PROJECT_REGISTRATION_TOKEN"
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.custom]
build_dir = "/tmp/gerrit-sync"
创建同步脚本/opt/gerrit-sync/sync.sh:
bash复制#!/bin/bash
git fetch origin +refs/heads/*:refs/heads/* --prune
git push gerrit HEAD:refs/for/master
5.3 权限管理策略
建议权限划分:
| 角色 | GitLab权限 | Gerrit权限 |
|---|---|---|
| 开发者 | Developer | Submit, Push, Label-Code |
| 审核者 | Maintainer | Label-Verified, +2 |
| 管理员 | Owner | Admin, Abandon |
Gerrit的权限通过/srv/gerrit/etc/groups文件配置,例如:
code复制[administrators]
admin
[reviewers]
user1
user2
6. 维护与监控
6.1 日常维护命令
GitLab:
bash复制# 检查服务状态
docker exec -it gitlab gitlab-ctl status
# 备份(会生成/var/opt/gitlab/backups/目录下的tar文件)
docker exec -it gitlab gitlab-rake gitlab:backup:create
# 恢复备份
docker exec -it gitlab gitlab-rake gitlab:backup:restore BACKUP=timestamp
Gerrit:
bash复制# 重建索引(当搜索异常时)
docker exec -it gerrit java -jar /var/gerrit/bin/gerrit.war reindex
# 查看日志
docker logs --tail 100 gerrit
6.2 监控方案建议
-
基础监控:
- 使用
docker stats查看实时资源占用 - 设置Prometheus监控:
yaml复制# GitLab配置 prometheus['enable'] = true node_exporter['enable'] = true
- 使用
-
日志收集:
- ELK Stack收集和分析日志
- 配置logrotate防止日志膨胀:
bash复制docker exec -it gitlab bash -c "echo '/var/log/gitlab/*.log { rotate 7 daily missingok notifempty delaycompress sharedscripts }' > /etc/logrotate.d/gitlab"
-
健康检查:
bash复制# GitLab健康检查 curl -s http://gitlab.example.com/-/health | jq . # Gerrit健康检查 curl -s http://gerrit.example.com/health | jq .
7. 性能调优实战经验
7.1 GitLab性能优化
数据库调优:
ruby复制# /etc/gitlab/gitlab.rb
postgresql['shared_buffers'] = "256MB" # 建议为总内存的25%
postgresql['work_mem'] = "8MB" # 每个查询操作的内存
postgresql['effective_cache_size'] = "768MB" # 建议为总内存的50-75%
Unicorn优化:
ruby复制unicorn['worker_timeout'] = 60
unicorn['worker_processes'] = 4 # CPU核心数+1
unicorn['worker_memory_limit_min'] = "200MB"
unicorn['worker_memory_limit_max'] = "300MB"
7.2 Gerrit性能优化
JVM参数调整:
ini复制[container]
javaOptions = -Xmx4g -Xms2g -XX:MaxRAMPercentage=70.0
user = gerrit
javaHome = /usr/lib/jvm/java-11-openjdk
缓存配置:
ini复制[cache "projects"]
maxAge = 1 hour
[cache "git_tags"]
maxAge = 30 minutes
7.3 存储优化技巧
-
使用
git gc定期清理仓库:bash复制docker exec -it gitlab bash -c "sudo -u git -H find /var/opt/gitlab/git-data/repositories -name '*.git' -type d -exec sh -c 'cd {} && git gc --aggressive' \;" -
启用GitLab存储自动压缩:
ruby复制gitlab_rails['housekeeping_optimize_repository_period'] = 1 gitlab_rails['housekeeping_full_repack_period'] = 10 gitlab_rails['housekeeping_gc_period'] = 30 -
Gerrit启用SSD缓存:
ini复制[cache "ssd"] directory = /var/gerrit/cache/ssd maxSize = 10g
8. 安全加固措施
8.1 基础安全配置
GitLab:
ruby复制# /etc/gitlab/gitlab.rb
gitlab_rails['gitlab_default_can_create_group'] = false
gitlab_rails['password_authentication_enabled_for_web'] = true
gitlab_rails['password_authentication_enabled_for_git'] = false # 强制SSH
Gerrit:
ini复制[auth]
secureStoreClass = com.googlesource.gerrit.plugins.securestore.FileSecureStore
[sshd]
listenAddress = *:29418
threads = 2
8.2 网络隔离方案
建议使用Docker网络隔离:
bash复制docker network create code-review-net
更新docker-compose文件:
yaml复制networks:
default:
name: code-review-net
driver: bridge
配置防火墙规则:
bash复制sudo ufw allow from 192.168.1.0/24 to any port 80,443 proto tcp
sudo ufw allow from 192.168.1.100 to any port 29418 proto tcp # 仅允许CI服务器访问Gerrit
8.3 备份策略
GitLab全量备份:
bash复制docker exec -it gitlab gitlab-rake gitlab:backup:create CRON=1
Gerrit增量备份:
bash复制docker exec -it gerrit bash -c "rsync -avz --delete /var/gerrit/git/ /backup/gerrit/git/"
设置定时任务(crontab -e):
bash复制0 2 * * * /usr/bin/docker exec gitlab gitlab-rake gitlab:backup:create CRON=1
0 3 * * * /usr/bin/docker exec gerrit rsync -avz --delete /var/gerrit/git/ /backup/gerrit/git/
9. 迁移与升级指南
9.1 GitLab版本升级
-
停止容器:
bash复制
docker stop gitlab -
备份数据:
bash复制docker exec -it gitlab gitlab-rake gitlab:backup:create cp -r /srv/gitlab /backup/gitlab-$(date +%F) -
拉取新镜像:
bash复制
docker pull gitlab/gitlab-ce:latest -
重新创建容器(使用相同参数)
9.2 Gerrit数据迁移
-
导出所有项目:
bash复制docker exec -it gerrit bash -c "java -jar /var/gerrit/bin/gerrit.war export --all-projects --format json > /var/gerrit/backup/gerrit-export-$(date +%F).json" -
在新服务器导入:
bash复制docker exec -it new_gerrit bash -c "java -jar /var/gerrit/bin/gerrit.war import --json < /var/gerrit/backup/gerrit-export.json"
9.3 回滚方案
GitLab回滚步骤:
- 停止当前容器
- 恢复备份:
bash复制
docker run --detach \ --hostname gitlab.example.com \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:previous_version - 恢复备份文件:
bash复制docker exec -it gitlab gitlab-rake gitlab:backup:restore BACKUP=timestamp
10. 扩展与集成
10.1 与CI/CD流水线集成
GitLab CI示例:
yaml复制stages:
- build
- test
- deploy
build_job:
stage: build
script:
- mvn clean package
only:
- merge_requests
gerrit_verify:
stage: test
script:
- ssh -p 29418 gerrit.example.com gerrit verify-project ${CI_PROJECT_PATH}
Gerrit Trigger配置:
- 安装Gerrit Trigger插件
- 在Jenkins中配置Gerrit服务器信息
- 设置事件触发规则(如patchset created)
10.2 插件生态系统
GitLab推荐插件:
- Mattermost:团队沟通
- Jira:问题跟踪
- Kubernetes:容器编排
Gerrit必备插件:
- reviewers:自动添加评审人
- delete-project:项目删除
- webhooks:事件通知
安装示例:
bash复制docker exec -it gerrit bash -c "java -jar /var/gerrit/bin/gerrit.war install-plugin --online delete-project"
10.3 高可用方案设计
GitLab HA架构:
- PostgreSQL主从复制
- Redis哨兵集群
- 多个GitLab Rails节点共享NFS
Gerrit多主架构:
- 使用Gerrit的多主插件
- 共享Git仓库存储(NFS或Gitaly)
- 负载均衡器分发请求
配置示例:
ini复制[gerrit]
serverId = gerrit-01
[peer]
strategy = jgroups
[jgroups "tcp"]
bindPort = 7800