Gerrit 3.14 Docker Compose 部署实战

官方 gerritcodereview/gerrit 3.14.4 镜像 Compose 部署实测:自动 init、数据目录属主、HTTP Basic/LDAP 认证路径、SSH 密钥接入、首个 Change 推送合入闭环、JVM 堆与 H2/PostgreSQL 数据库选型,附 k8s gerrit-operator 生态与排障实录。

GerritGerrit版本控制2026/10/27

Gerrit 3.14 Docker Compose 部署实战

目标:从零开始用官方 gerritcodereview/gerrit 镜像 + Docker Compose 部署一套可用的 Gerrit 3.14.4 代码评审服务,覆盖自动 init、认证路径(开发者模式 / HTTP Basic 反代 / LDAP)、SSH 密钥接入、首个 Change 的推送与合入验证,并把部署全程踩到的坑沉淀为排障实录。已在 Ubuntu 22.04 + Docker Compose v2 环境实测通过(Gerrit 3.14.4,2026-10-27)。

一、环境信息

  • 操作系统:Ubuntu 22.04(64 位,内核 5.15+)
  • Gerrit 版本:3.14.4(官方镜像 gerritcodereview/gerrit:3.14.4,压缩体积约 1.52 GB,2026-10-27 拉取)
  • 运行时:Docker 28 + Docker Compose v2(docker compose 子命令)
  • 反向代理:nginx:1-alpine(HTTP Basic 认证层)
  • 数据库:H2(镜像内嵌默认,生产可切 PostgreSQL/MySQL,见第十节)
  • 端口规划:Web(HTTP)对外 8141(Gerrit 内部 8080),Git SSH 对外 8148(Gerrit 内部标准端口 29418)
  • 内网:自定义 bridge 网络 gerrit-3.14.4-net,子网 10.89.68.0/24
  • Compose 项目名:gerrit-3.14.4-stack
  • 演示管理账号:admin / q1w2e3r4(HTTP Basic 与 Gerrit HTTP 凭据一致)
  • JVM 堆:-Xms256m -Xmx512m(见第七节修改位置与验证)

二、镜像选型说明

Gerrit 官方在 Docker Hub 维护 gerritcodereview/gerrit 镜像(GerritForge 与 Google 社区发布),选型要点:

候选结论
gerritcodereview/gerrit:3.14.4本篇采用。官方镜像,内部自动 init --batch,开箱即用,版本与官方 war 完全一致
gerritcodereview/gerrit:latest跟随最新稳定版,但生产不建议用浮动 tag
gerritforge/gerritGerritForge 商业发行版镜像,含企业插件(replication 增强等),需商业授权场景选
自行打 war 镜像仅当需要裁剪插件/定制 JRE 时考虑,维护成本高

官方镜像要点(来自镜像入口脚本实测):

  1. 首次启动检测到 /var/gerrit/etc/gerrit.config 不存在时,自动执行 gerrit.war init --batch --install-all-plugins -d /var/gerrit,随后 reindex 全量重建索引;
  2. 内部运行用户为 gerrit(uid/gid 1000),所有 bind mount 数据目录属主必须是 1000:1000(踩坑实录见第十三节 13.1);
  3. 入口脚本会覆盖外部传入的 JAVA_OPTS 环境变量并按自己的值执行 init/reindex(踩坑实录见 13.2),JVM 参数的正确落点是 gerrit.config 的 [container] 段。

三、前置条件

  1. 已安装 Docker 24+ 与 Docker Compose v2:
docker --version && docker compose version

实测回显:

Docker version 28.4.0, build a5b0b6b
Docker Compose version v2.39.2
  1. 服务器可用内存 ≥ 2 GB(Gerrit 堆 512 MB + 索引/缓存开销),磁盘 ≥ 5 GB;
  2. 计划使用的宿主端口未被占用(本篇用 8141/8148),确认方式:
ss -ltn | grep -E ':(8141|8148)\b' || echo 'ports free'

实测回显:

ports free
  1. 宿主机已有可用的 git 客户端与 ssh 客户端(用于后续验证评审流程)。

四、部署步骤

4.1 目录规划

mkdir -p /opt/gerrit-3.14.4/{compose,etc,git,db,index,cache,nginx}
cd /opt/gerrit-3.14.4

⚠️ 本篇以 /opt/gerrit-3.14.4 为部署根目录,下文所有相对路径均基于该目录。

4.2 修正数据目录属主(关键,勿跳过)

官方镜像内进程以 uid/gid 1000 运行,bind mount 的五个数据目录必须提前赋予属主,否则首次 init 直接失败(报错实录见 13.1):

chown -R 1000:1000 etc git db index cache

验证:

ls -ldn etc git db index cache | awk '{print $3":"$4, $9}'

实测回显:

1000:1000 etc
1000:1000 git
1000:1000 db
1000:1000 index
1000:1000 cache

4.3 编写 docker-compose.yml

name: gerrit-3.14.4-stack

services:
  gerrit:
    image: gerritcodereview/gerrit:3.14.4
    container_name: gerrit-3.14.4-app
    ports:
      - "8148:29418"          # Git/SSH 命令端口(Gerrit 标准端口 29418 映射到宿主 8148)
    environment:
      - CANONICAL_WEB_URL=http://localhost:8141
    volumes:
      - ./etc:/var/gerrit/etc
      - ./git:/var/gerrit/git
      - ./db:/var/gerrit/db
      - ./index:/var/gerrit/index
      - ./cache:/var/gerrit/cache
    networks:
      - gerrit-net

  nginx:
    image: nginx:1-alpine
    container_name: gerrit-3.14.4-gateway
    ports:
      - "8141:80"             # Web UI 与 REST API 入口
    volumes:
      - ./nginx/gerrit.conf:/etc/nginx/conf.d/default.conf:ro
      - ./nginx/htpasswd:/etc/nginx/htpasswd:ro
    depends_on:
      - gerrit
    networks:
      - gerrit-net

networks:
  gerrit-net:
    name: gerrit-3.14.4-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.68.0/24

配置解读:

  • name: gerrit-3.14.4-stack:显式声明 Compose 项目名,避免与同机其他 Compose 项目同名互相误删;
  • 端口只暴露两个:Web 8141(走 nginx 认证)、SSH 8148(直连 Gerrit);
  • 五个数据卷全部 bind mount 到宿主目录,便于备份与迁移(见第五节);
  • CANONICAL_WEB_URL 决定 Gerrit 对外展示的链接基地址(评审通知邮件、Change URL 都用它),要与实际访问地址一致。

4.4 编写 nginx 反代配置与 htpasswd

nginx/gerrit.conf:

server {
    listen 80;
    server_name _;

    location / {
        auth_basic "Gerrit Code Review";
        auth_basic_user_file /etc/nginx/htpasswd;
        proxy_pass http://gerrit:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header REMOTE_USER $remote_user;
        proxy_read_timeout 300;
        client_max_body_size 0;
    }
}

生成 htpasswd(演示账号 admin / q1w2e3r4):

printf 'admin:' > nginx/htpasswd
echo -n 'q1w2e3r4' | openssl passwd -apr1 -stdin >> nginx/htpasswd
chown 1000:1000 nginx/htpasswd
cat nginx/htpasswd

实测回显:

admin:$apr1$HDpgb.w5$LlGgi1Qmd6qcZEoAJcbzy.

4.5 启动与首次 init 观测

docker compose up -d

首次启动自动 init + reindex 约需 20–60 秒,观察日志:

docker logs gerrit-3.14.4-app 2>&1 | tail -15

实测回显(输出节选,实测首尾):

[2026-10-27T13:04:08.671Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin uploadvalidator, version v3.0.0-rc1-331-ga8b5d4ffa9
[2026-10-27T13:04:08.698Z] [main] INFO  com.google.gerrit.server.plugins.PluginLoader : Loaded plugin webhooks, version v3.14.4
[2026-10-27T13:04:08.729Z] [main] INFO  com.google.gerrit.sshd.SshDaemon : Started Gerrit APACHE-SSHD-2.19.0 on *:29418
[2026-10-27T13:04:08.733Z] [main] INFO  org.eclipse.jetty.server.Server : jetty-12.1.10; built: 2026-05-31T04:45:52.925Z; jvm 21.0.12.1+1-LTS
[2026-10-27T13:04:09.256Z] [main] INFO  org.eclipse.jetty.server.handler.ContextHandler : Started oeje8n.ContextHandler$CoreContextHandler@68344a08{ROOT,/,b=null,a=AVAILABLE,...}
[2026-10-27T13:04:09.263Z] [main] INFO  org.eclipse.jetty.server.AbstractConnector : Started oejs.ServerConnector@2295b060{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
[2026-10-27T13:04:09.265Z] [main] INFO  com.google.gerrit.pgm.Daemon : Gerrit Code Review 3.14.4 ready

Gerrit Code Review 3.14.4 ready 即初始化完成;默认已加载的官方插件:gitiles、hooks、plugin-manager、replication、reviewnotes、singleusergroup、uploadvalidator、webhooks、delete-project。

4.6 部署验证

docker compose ps

实测回显:

NAME                    IMAGE                          COMMAND                  SERVICE   CREATED          STATUS         PORTS
gerrit-3.14.4-app       gerritcodereview/gerrit:3.14.4  "/bin/entrypoint.sh …"   gerrit    3 minutes ago    Up 3 minutes   0.0.0.0:8148->29418/tcp
gerrit-3.14.4-gateway   nginx:1-alpine                 "/docker-entrypoint.…"   nginx     3 minutes ago    Up 3 minutes   0.0.0.0:8141->80/tcp

服务版本与认证入口验证:

curl -s -u admin:q1w2e3r4 http://localhost:8141/config/server/version
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8141/

实测回显:

)]}'
"3.14.4"

401

两点解读:REST 响应开头的 )]}' 是 Gerrit 防跨站 JSON 劫持的魔法前缀,所有 REST 响应都带,解析 JSON 前先剥离这一行;无凭据访问返回 401 说明 nginx Basic 认证层已生效。

五、数据持久化说明

五个 bind mount 目录与内容对应关系:

宿主目录Gerrit 内部路径内容备份优先级
etc/var/gerrit/etcgerrit.config、secure.config、密钥、插件 jar最高(丢失需重配)
git/var/gerrit/git全部 Git 裸仓库 + NoteDb 评审元数据(All-Projects、All-Users、各项目)最高(核心资产)
db/var/gerrit/dbH2 数据库文件(账户/群组索引等少量实体)高
index/var/gerrit/indexLucene 二级索引可重建(升级后建议 reindex)
cache/var/gerrit/cache运行缓存可丢弃

整机备份一条命令即可完成(停写窗口内执行):

docker compose down && tar czf gerrit-backup-$(date +%F).tgz etc git db && docker compose up -d

💡 技术拓展:Gerrit 的元数据库选型不止 H2。常见三选一对比——

数据库特点适用场景
H2(内嵌文件库)零部署、随站点目录持久化单机中小团队(本篇默认)
PostgreSQL生产级、备份恢复生态成熟中大规模、多实例共享元数据
MariaDB/MySQL生产级、DBA 运维存量多已有 MySQL 运维体系的组织

NoteDb 机制落地后(3.0 起),评审元数据存于 Git refs,关系库只存账户/群组,切换成本远低于传统 forge。本篇实测采用 H2,生产多实例建议 PostgreSQL(配置见第十节)。

六、环境变量表

官方镜像支持的核心环境变量(实测行为):

变量示例值作用与注意
CANONICAL_WEB_URLhttp://localhost:8141对外基地址,生成 Change/邮件链接的根;写错会导致页面跳转异常
JAVA_OPTS-Xms256m -Xmx512m⚠️ 会被镜像入口脚本覆盖(仅 init/reindex 阶段生效),堆参数请写进 gerrit.config,见 13.2
HTTPD_LISTEN_URLproxy-http://*:8080/自定义 HTTP 监听(默认 http://*:8080/),一般不改
SSHD_LISTEN_URL*:29418自定义 SSH 监听(默认 *:29418),一般不改

七、配置参数说明

首次自动 init 会在 etc/gerrit.config 生成主配置(etc/secure.config 存密钥类配置)。本篇实测生成的初始文件:

[gerrit]
	basePath = git
	canonicalWebUrl = http://localhost:8141
	serverId = 4019fa49-0f3f-41c3-b794-5405c7edbb13
[container]
	javaOptions = "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
	javaOptions = "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
	user = gerrit
	javaHome = /usr/lib/jvm/java-21-openjdk-21.0.12.1.1-1.2.el9.alma.1.x86_64
	javaOptions = -Djava.security.egd=file:/dev/./urandom
	javaOptions = --add-opens java.base/java.net=ALL-UNNAMED
	javaOptions = --add-opens java.base/java.lang.invoke=ALL-UNNAMED
[index]
	type = lucene
[auth]
	type = OPENID
[receive]
	enableSignedPush = false
[sendemail]
	smtpServer = localhost
[sshd]
	listenAddress = *:29418
[httpd]
	listenUrl = http://*:8080/
[cache]
	directory = cache

逐项说明:

  • [gerrit] basePath:Git 仓库根(相对站点目录,即 /var/gerrit/git);serverId 是站点全局唯一 ID(Change-Id 命名空间),不可变更,否则历史 Change 全部失联;
  • [container] user:进程运行用户(gerrit);javaHome:init 自动探测的 JVM;javaOptions:JVM 参数行,在此追加堆限制(见下方);
  • [index] type = lucene:二级索引引擎,大规模站点可换 elasticsearch;
  • [auth] type = OPENID:自动 init 的默认认证(公网开放注册型),内网/生产应改为 DEVELOPMENT_BECOME_ANY_ACCOUNT(体验)或 HTTP/LDAP(生产),见 4.7;
  • [receive] enableSignedPush = false:GPG 签名推送开关;
  • [sshd] listenAddress = *:29418:Git/SSH 命令监听;[httpd] listenUrl = http://*:8080/:Web/REST 监听。

按 JVM 规范将堆限制写入 [container](编辑 etc/gerrit.config,在 [container] 段追加一行):

[container]
	javaOptions = -Xms256m -Xmx512m

重启后验证生效:

docker compose restart && sleep 30
docker exec gerrit-3.14.4-app sh -c "cat /proc/1/cmdline | tr '\0' ' '" | grep -oE '\-Xms[0-9]+m -Xmx[0-9]+m'

实测回显:

-Xms256m -Xmx512m

八、配置文件挂载

需要长期维护的配置文件全部集中在宿主 etc/ 与 nginx/:

文件挂载点用途
etc/gerrit.config/var/gerrit/etc/gerrit.config主配置(本篇第七节逐项详解的对象)
etc/secure.config/var/gerrit/etc/secure.config密钥类配置(数据库口令、SMTP 密码、LDAP bind 密码)
etc/mail/var/gerrit/etc/mail邮件模板目录(init 自动创建)
etc/plugins/*.jar/var/gerrit/etc/plugins外挂插件存放目录
nginx/gerrit.conf/etc/nginx/conf.d/default.conf反代认证层配置

改动 gerrit.config 后的生效方式:重启栈(docker compose restart)。改动后 Gerrit 启动日志出现 Daemon : Gerrit Code Review 3.14.4 ready 即新配置已加载。

九、等价 docker run

不经 Compose 的等价最小启动(官网首页 Getting Started 的 Docker 路径原文,可先用它快速验证镜像可用):

docker run -d \
 -p 8080:8080 \
 -p 29418:29418 \
 --name gerrit \
 gerritcodereview/gerrit:latest

与本篇 Compose 等价的完整形态(含认证网关与数据目录,等价于 4.3–4.5 的效果):

docker run -d \
 --name gerrit-3.14.4-app \
 -p 8148:29418 \
 -e CANONICAL_WEB_URL=http://localhost:8141 \
 -v /opt/gerrit-3.14.4/etc:/var/gerrit/etc \
 -v /opt/gerrit-3.14.4/git:/var/gerrit/git \
 -v /opt/gerrit-3.14.4/db:/var/gerrit/db \
 -v /opt/gerrit-3.14.4/index:/var/gerrit/index \
 -v /opt/gerrit-3.14.4/cache:/var/gerrit/cache \
 --network gerrit-3.14.4-net \
 gerritcodereview/gerrit:3.14.4

生产建议用 Compose 管理生命周期(网络、依赖、重启策略一致性强);docker run 仅作单容器快速验证与排障对照。

十、数据库选型与 PostgreSQL 配置说明

默认 H2 适合中小团队;需要 PostgreSQL 时三步切换(配置形态实测自官方文档 config-gerrit 的 [database] 段,生产上线前按此执行):

  1. Compose 增加数据库服务(以官方 postgres:16 镜像为例):
  db:
    image: postgres:16-alpine
    container_name: gerrit-3.14.4-db
    environment:
      - POSTGRES_USER=gerrit
      - POSTGRES_PASSWORD=q1w2e3r4
      - POSTGRES_DB=reviewdb
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    networks:
      - gerrit-net
  1. etc/gerrit.config 增加 [database] 段:
[database]
	type = postgresql
	hostname = db
	database = reviewdb
	username = gerrit
  1. etc/secure.config 增加口令(密码类配置不入主配置):
[database]
	password = q1w2e3r4

重启后首次启动 Gerrit 会自动建表(日志可见 ReviewedDb 初始化行)。注意:H2 → PostgreSQL 切换属站点迁移(Gerrit 无在线迁移工具,需导出仓库重新 init),新站点直接选定数据库类型最省事。

十一、认证路径:init 向导与三种认证模式

自动 init 生成的默认认证是 OPENID(公网开放注册型,依赖公网 OpenID 提供商)。真实部署按团队形态三选一(改 etc/gerrit.config 的 [auth] type 后重启生效):

11.1 开发者快速模式(DEVELOPMENT_BECOME_ANY_ACCOUNT)

[auth]
	type = DEVELOPMENT_BECOME_ANY_ACCOUNT

登录页提供「Become Account」切换表单(按 user_name / preferred_email / account_id 三种方式切换),首次使用先点「New Account」创建账户,再在 REST 里补全用户名与凭据。以下为本环境实测的完整建户过程(curl 交互):

# 1. 打开登录页拿会话与 XSRF cookie
curl -s -c cookie.jar 'http://localhost:8141/login/'
# 2. 创建新账户(POST action=create_account)
curl -s -b cookie.jar -c cookie.jar -X POST -d 'action=create_account' 'http://localhost:8141/login/'
# 3. 设置 username=admin(写 REST 需带 X-Gerrit-Auth=cookie 里的 XSRF_TOKEN 值)
XSRF=$(grep XSRF_TOKEN cookie.jar | awk '{print $NF}')
curl -s -b cookie.jar -X PUT -H "X-Gerrit-Auth: $XSRF" -H 'Content-Type: application/json' \
  -d '{"username":"admin"}' 'http://localhost:8141/a/accounts/self/username'

第 3 步实测回显:

)]}'
"admin"

验证账户:

curl -s 'http://localhost:8141/a/accounts/admin/detail'

实测回显:

)]}'
{"registered_on":"2026-10-27 13:16:06.000000000","_account_id":1000000,"name":"admin","secondary_emails":[],"username":"admin","avatars":[...]}

⚠️ 仅限内网体验环境使用:任何能访问页面的人都能切换成任意账户,生产禁止。

11.2 HTTP Basic 认证(反代网关模式,本篇主线)

auth.type = HTTP 表示认证由反向代理完成、Gerrit 信任代理注入的用户身份(REMOTE_USER 头)。配合 4.4 的 nginx auth_basic 与 htpasswd 即构成完整 HTTP 认证链路。实操要点(实测踩坑结论):

  1. Gerrit 侧给账户设置 HTTP 凭据(3.13 起官方推荐 token 化凭据):
curl -s -X PUT -H 'Content-Type: application/json' \
  -d '{"http_password":"q1w2e3r4"}' \
  'http://localhost:8141/a/accounts/self/password.http'

实测回显(201 Created):

)]}'
"q1w2e3r4"
  1. 之后所有 REST API 与 git-over-HTTP 都可用 admin:q1w2e3r4 走 Basic(nginx 校验 htpasswd,Gerrit 校验账户凭据,双层一致最稳);
  2. 若直接把 auth.type = HTTP 用于裸连(无代理)场景,Gerrit 收不到 REMOTE_USER 会拒绝(/a/ 一律 401),报错形态见 13.4;
  3. 注意 nginx 默认会透传客户端 Authorization 头,Basic 双层认证时保持透传即可,不要在代理层清空该头(曾实测因清空导致 REST 401,见 13.4)。

11.3 LDAP 认证(企业目录模式)

企业普遍用 LDAP 对接公司目录(3.14 支持 LDAP 与 LDAP_BIND 两种后端)。标准配置形态(官方 config-authentication 文档样例字段):

[auth]
	type = LDAP
[ldap]
	server = ldap://ldap.example.com
	username = uid=gerrit,ou=service,dc=example,dc=com
	accountBase = ou=people,dc=example,dc=com
	accountPattern = (&(objectClass=person)(uid=${username}))
	accountFullName = displayName
	accountEmailAddress = mail
	groupBase = ou=groups,dc=example,dc=com

对应口令写 etc/secure.config:

[ldap]
	password = ${LDAP_BIND_PASSWORD}

LDAP 模式下用户首次登录自动建户(auth.autoCreateAccount 默认开启),本地无需手工建户。本篇未起独立 LDAP 服务器做端到端实测,以上为官方文档形态的标准配置,上线前建议先用 ldapsearch 验证 bind 与查询表达式。

十二、SSH 密钥接入与首个 Change 闭环(部署验收)

部署验收以「推一个 Change、打分、合入」为完成标志,同时验证 SSH 面可用:

  1. 生成并注册 SSH 公钥(ed25519):
ssh-keygen -t ed25519 -f ~/.ssh/gerrit_demo -N '' -C admin@demo -q
curl -s -u admin:q1w2e3r4 -X POST -H 'Content-Type: text/plain' \
  --data-binary @~/.ssh/gerrit_demo.pub \
  'http://localhost:8141/a/accounts/self/sshkeys'

实测回显(201):

)]}'
{"seq":1,"ssh_public_key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAeP...","algorithm":"ssh-ed25519","comment":"admin@demo","valid":true}
  1. SSH 连通与建项目:
ssh -i ~/.ssh/gerrit_demo -p 8148 admin@localhost gerrit version
ssh -i ~/.ssh/gerrit_demo -p 8148 admin@localhost gerrit create-project demo-project
ssh -i ~/.ssh/gerrit_demo -p 8148 admin@localhost gerrit ls-projects

实测回显:

gerrit version 3.14.4
All-Projects
All-Users
demo-project
  1. clone、提交并推送到魔术分支 refs/for/master(Change 的产生方式):
git clone "ssh://admin@localhost:8148/demo-project" && cd demo-project
git config user.name admin && git config user.email admin@demo.com
echo 'hello gerrit review flow' > README.md
git add README.md
git commit -m 'Add README

Change-Id: I1234567890abcdef1234567890abcdef12345678'
git push origin HEAD:refs/for/master

实测回显(输出节选):

remote: Processing changes: refs: 1, new: 1, done
remote:
remote: SUCCESS
remote:
remote:   http://localhost:8141/c/demo-project/+/1 Add README [NEW]
To ssh://localhost:8148/demo-project
 * [new reference]   HEAD -> refs/for/master
  1. REST 打 Code-Review +2 并 submit 合入:
curl -s -u admin:q1w2e3r4 -X POST -H 'Content-Type: application/json' \
  -d '{"labels":{"Code-Review":2},"message":"LGTM"}' \
  'http://localhost:8141/a/changes/1/revisions/current/review' | head -1
curl -s -u admin:q1w2e3r4 -X POST -H 'Content-Type: application/json' -d '{}' \
  'http://localhost:8141/a/changes/1/submit' | grep -oE '"status":"[A-Z]+"'

实测回显:

)]}'

"status":"MERGED"

status: MERGED 即评审合入闭环完成,部署验收通过。SSH 命令与 REST API 的更多用法见本专栏命令篇(发布后互链)。

十三、常用运维命令

cd /opt/gerrit-3.14.4

docker compose ps                       # 栈状态(见 4.6 回显)
docker logs -f gerrit-3.14.4-app        # 实时日志(排障第一入口)
docker compose restart                  # 改配置后重启生效
docker compose down                     # 停栈(数据在宿主目录不受影响)
docker compose up -d                    # 起栈

缓存与运行状态可通过 Gerrit SSH 命令面查看(管理员账户):

ssh -i ~/.ssh/gerrit_demo -p 8148 admin@localhost 'gerrit show-caches --width 80'

实测回显(输出节选,实测首尾):

Gerrit Code Review        3.14.4                    now    13:25:08   UTC
                                                 uptime     3 min 16 sec

  Name                          |Entries              |  AvgGet |Hit Ratio|
                                |   Mem   Disk   Space|         |Mem  Disk|
--------------------------------+---------------------+---------+---------+
  adv_bases                     |                     |         |         |
  change_notes                  |     6               |   5.0ms | 91%     |
  changeid_project              |     2               |         | 87%     |
  default_preferences           |                     |         |         |
  external_ids_map              |     2               |         | 97%     |
  groups                        |                     |   4.7ms |  0%     |

十四、Kubernetes 部署形态(gerrit-operator 生态)

除 Compose/裸机外,Gerrit 在 Kubernetes 侧有社区运维生态,本节为联网溯源整理(查询日期 2026-10-27,来源:官网 releases/GerritForge 博客、k8s-gerrit 项目文档;本批未做 k8s 集群实测,后续集群实测另行验证):

  • k8s-gerrit 项目:由 SAP 与 GerritForge 于 2018 年合作发起(GerritForge 官方博客:「The code has been published to the new k8s-gerrit repository」),提供 Helm Chart 形态的 Gerrit Kubernetes 部署,含共享存储、单主起步与平滑升级路径;GerritForge 2025 路线图明确「k8s-Gerrit initiative will improve Gerrit's deployment on Kubernetes」(Gerrit 3.13 版本周期内持续推进)。
  • Gerrit Operator:k8s-gerrit 生态提供的 Kubernetes Operator,通过 CRD(如 GerritCluster)声明式管理 Gerrit 站点:自动化部署与扩缩容、内置 Ingress 管理(目前官方文档标注仅支持 Nginx Ingress Controller)、组件级资源声明(API 参考含 replicas/resources/priorityClassName 等字段)。
  • 适用判断:单机评审场景用本篇 Compose 形态即可;多站点高可用(multi-site 插件 + 双活)或大规模托管场景再引入 k8s 形态,避免小规模过度工程化。

十五、常见问题(FAQ)

15.1 启动即报 fatal: Cannot make directory /var/gerrit/etc/mail

现象(实测日志):

Initializing Gerrit site ...
[2026-10-27 13:03:16,562] [main] INFO  com.google.gerrit.server.config.GerritServerConfigProvider : No /var/gerrit/etc/gerrit.config; assuming defaults
fatal: /var/gerrit/etc/mail
fatal: Cannot make directory /var/gerrit/etc/mail

原因:bind mount 数据目录属主不是 uid 1000(镜像内 gerrit 用户),init 无权写入。解决:chown -R 1000:1000 etc git db index cache 后重新 docker compose up -d。

15.2 JAVA_OPTS 环境变量设置了但堆没变

原因:镜像入口脚本第一行 export JAVA_OPTS='--add-opens ...' 覆盖了外部传入值,且 daemon 运行参数只读 gerrit.config 的 container.javaOptions。解决:堆参数写入 etc/gerrit.config(第七节),重启并用 /proc/1/cmdline 验证(回显见第七节)。

15.3 端口被占用:failed to bind host port ... address already in use

原因:宿主端口已被其他进程/Compose 项目占用。解决:换宿主侧映射端口(本篇 SSH 从 29418 改映射 8148 即此原因),Compose 里改 ports: 左侧宿主端口即可,Gerrit 内部端口无需动;改完 docker compose up -d 重建。

15.4 auth.type = HTTP 下 REST 一律 401(account inactive or not provisioned in Gerrit)

现象(实测日志):

WARN  com.google.gerrit.httpd.ProjectBasicAuthFilter : Authentication failed for admin: account inactive or not provisioned in Gerrit

定位过程与结论:该 401 说明请求既无有效 REMOTE_USER 上下文、账户也未预置 HTTP 凭据。两步修复:① 账户侧先设置 HTTP 凭据(11.2 第 1 步 password.http);② 代理层确认 REMOTE_USER 头注入且未清空 Authorization 头。本篇实测中「代理清空 Authorization 头 + 账户未设凭据」两者叠加时表现为持续 401,逐一修复后 Basic 认证恢复 200。

15.5 推送被拒:change ... closed

现象(实测回显):

 ! [remote rejected] HEAD -> refs/for/master (change http://localhost:8141/c/demo-project/+/1 closed)

原因:Change 已合入(MERGED)后,再用同一个 Change-Id 推送会被拒绝——closed 状态的 Change 不能追加 patchset。解决:修改提交信息换新 Change-Id(git commit --amend)后重推,产生全新的 Change。

15.6 gerrit review 报 is not a valid patch set

原因:3.x 的 SSH 评分命令参数格式是 CHANGE,PATCHSET 逗号组合(如 2,1),裸写 change 号会被当作 patch set 解析失败。另外注意:2.x 时代的 gerrit approve、gerrit set-review、gerrit ls-users 命令在 3.14 已不存在(实测均报 not found),评分与评审人管理分别用 gerrit review 与 gerrit set-reviewers。

15.7 日志中的 GuiceFilter/AssistedInject WARNING 是否需要处理

WARNING: Multiple Servlet injectors detected. ...
WARNING: AssistedInject factory ... will be slow because ...

两者均为插件装载期的通用告警(官方镜像默认输出),不影响功能,无需处理;若关注 replication 插件那 6500% 提示的性能注记,按官方建议升级插件版本即可。

十六、参考链接

  1. 官方镜像(Docker Hub):https://hub.docker.com/r/gerritcodereview/gerrit
  2. Gerrit 官网下载页:https://www.gerritcodereview.com/
  3. 版本发布总览:https://www.gerritcodereview.com/releases/README.md
  4. 官方配置文档(config-gerrit):https://gerrit-review.googlesource.com/Documentation/config-gerrit.html
  5. 反向代理与 HTTP 认证文档:https://gerrit-review.googlesource.com/Documentation/config-reverseproxy.html
  6. 认证配置文档:https://gerrit-review.googlesource.com/Documentation/config-authentication.html
  7. REST API 文档:https://gerrit-review.googlesource.com/Documentation/rest-api.html
  8. k8s-gerrit 项目(SAP + GerritForge):https://gerritforge.com/
  9. 站内《Gerrit 介绍与选型指南》:https://www.quzuo.net/document/jBzSHXoP3n0J