Forgejo 16.0 Docker Compose 部署指南
用 Docker Compose 一键部署 Forgejo 16.0.6 自托管代码托管平台(PostgreSQL 后端、3100/3122 双端口、数据全持久化到 /opt/data/forgejo),覆盖 compose.yml 逐段解释、安装向导实测、建仓/push/Issue 硬性验收与常见问题。
Forgejo 16.0 Docker Compose 部署指南
> 目标:在一台 Ubuntu 22.04 服务器上,用 Docker Compose 从零部署 Forgejo 16.0.6(PostgreSQL 数据库后端),完成 Web 安装向导初始化,并通过「建仓 + git push + 建 Issue」三步硬性验收。全部命令与回显均在真实环境(Ubuntu 22.04、Forgejo 16.0.6、PostgreSQL 16)实测通过。
一、环境信息
本指南所有命令在以下环境中逐条实测,回显照抄真实输出:
- 操作系统:Ubuntu 22.04(x86_64)
- Forgejo:16.0.6(镜像
codeberg.org/forgejo/forgejo:16.0.6,实测docker images显示 279MB) - 数据库:PostgreSQL 16(镜像
postgres:16-alpine) - Docker:24.x(Compose v2 插件,
docker compose version可用) - 宿主端口分配:3100 → Forgejo HTTP 3000;3122 → Forgejo SSH 22
- 数据目录(宿主机持久化):
/opt/data/forgejo/ - 部署文件目录:
/opt/data/forgejo/(compose.yml与.env都放这里) - 部署完成后版本确认(实测):
curl -s http://localhost:3100/api/v1/version
{"version":"16.0.6+gitea-1.22.0"}
💡 说明:
16.0.6+gitea-1.22.0表示 Forgejo 16.0.6 基于 Gitea 1.22 内核(Forgejo 是 Gitea 的社区分叉,内核版本号会一直保留),这一条输出同时验证了 Web 服务与数据库连接都已就绪。
二、镜像选型说明
Forgejo 官方 OCI 镜像发布在 Codeberg 自己的 Registry(不发布到 Docker Hub),选型前先确认镜像地址与 tag 策略,避免拉到第三方搬运镜像。
| 镜像地址 | 说明 |
|---|---|
codeberg.org/forgejo/forgejo:16.0.6 | 官方主 Registry,本文实测使用的精确版本 tag |
codeberg.org/forgejo/forgejo:16.0 | 16.0 支线滚动 tag,自动跟随补丁版 |
codeberg.org/forgejo/forgejo:16 | 大版本滚动 tag,自动跟随 16.x 所有版本 |
codeberg.org/forgejo/forgejo:17.0.0 | 2026-10-15 发布的新支线首个版本(较新,未经历补丁打磨) |
data.forgejo.org/forgejo/forgejo:<tag> | 官方镜像站,tag 与 Codeberg 相同,部分网络环境访问更快 |
关键差异与如何选型:生产固定精确版本号(如 16.0.6),升级时机完全由自己控制;滚动 tag(16/16.0)方便但可能在你不知情时引入变更。本文选择 16.0.6——它是 16.0 稳定支线 2026-10-12 发布的最新补丁版,而 17.0.0 刚发布 2 天尚无补丁,新支线早期不建议直接上生产(升级方法见《Forgejo 16.0 运维手册》)。
⚠️ 拉取镜像时务必写全 Registry 前缀 codeberg.org/。只写 forgejo:16.0.6 会被 Docker 按短名规则去 Docker Hub 解析,实测报错:
docker pull forgejo:16.0.6
Error response from daemon: error from registry: 🚫 👀-> https://github.com/DaoCloud/public-image-mirror/issues/2328 🔗 这镜像不在白名单. this image is not in the allowlist.
三、前置条件
3.1 确认端口空闲
Forgejo 需要两个宿主端口:3100(Web/HTTP)、3122(Git over SSH)。部署前先确认未被占用:
ss -tlnp | grep -E ':3100|:3122'
实测端口空闲时该命令无任何输出(退出码 1),此时可以继续。若输出中已有监听进程,需要先腾出端口或调整下文的端口映射。
3.2 创建数据目录
所有持久化数据统一放 /opt/data/forgejo/,按用途分三个子目录并预置属主(Forgejo 容器内以 UID 1000 运行,PostgreSQL alpine 镜像内以 UID 70 运行):
mkdir -p /opt/data/forgejo/forgejo /opt/data/forgejo/db
chown -R 1000:1000 /opt/data/forgejo/forgejo
chown -R 70:70 /opt/data/forgejo/db
ls -la /opt/data/forgejo/
total 20
drwxrwxrwx 5 root root 4096 Oct 17 11:40 .
drwxr-xr-x 30 root root 4096 Oct 17 11:40 ..
drwxr-xr-x 2 70 70 4096 Oct 17 11:40 db
drwxr-xr-x 2 1000 1000 4096 Oct 17 11:40 forgejo
3.3 确认 Docker Compose 版本
docker compose version
Docker Compose version v2.39.2
Compose v2 为 docker compose(空格)子命令形式;若你的机器只有老的 v1 docker-compose,把下文所有 docker compose 替换为 docker-compose 即可。
四、部署步骤
4.1 编写 compose.yml
在 /opt/data/forgejo/ 创建 compose.yml,以下为本次实测使用的完整文件(先在 [部署文件目录] 准备好 .env 再启动,见 4.2):
services:
forgejo:
image: codeberg.org/forgejo/forgejo:16.0.6
container_name: forgejo-16.0.6-devops
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__database__DB_TYPE=postgres
- FORGEJO__database__HOST=forgejo-16-db:5432
- FORGEJO__database__NAME=forgejo
- FORGEJO__database__USER=forgejo
- FORGEJO__database__PASSWD=${FORGEJO_DB_PASSWORD}
networks:
- forgejo-net
volumes:
- /opt/data/forgejo/forgejo:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3100:3000"
- "3122:22"
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16-alpine
container_name: forgejo-16-db
environment:
- POSTGRES_USER=forgejo
- POSTGRES_PASSWORD=${FORGEJO_DB_PASSWORD}
- POSTGRES_DB=forgejo
networks:
- forgejo-net
volumes:
- /opt/data/forgejo/db:/var/lib/postgresql/data
restart: unless-stopped
networks:
forgejo-net:
driver: bridge
逐段解释:
image: codeberg.org/forgejo/forgejo:16.0.6:固定精确版本(选型理由见「二、镜像选型说明」)。container_name:显式命名,docker ps与日志排查时一眼可辨(避免 compose 自动生成的项目名前缀)。USER_UID/USER_GID=1000:Forgejo 容器内git运行用户的 UID/GID,设为 1000 与宿主机普通用户一致,/data(bind mount 到宿主/opt/data/forgejo/forgejo)里的文件属主就是可读写的,不会出现 root 归属导致备份困难的问题。FORGEJO__database__*环境变量:双下划线__映射app.ini的[database]段,如FORGEJO__database__HOST写入[database] HOST。这一组变量会在安装向导页面上预填数据库连接(实测见第五章),把最容易填错的数据库参数固定下来。FORGEJO__database__HOST=forgejo-16-db:5432:直接用 Compose 网络里的服务容器名做主机名——同一forgejo-net网络内置 DNS,容器名即主机名,IP 变化也不受影响。volumes三行挂载:/data是 Forgejo 全部数据(仓库裸库、附件、头像、LFS、日志、app.ini);/etc/timezone与/etc/localtime只读挂载让 Forgejo 显示的提交时间与宿主机时区一致。ports两行:3100:3000把 Web 暴露到宿主 3100;3122:22把内置 SSH 服务暴露到宿主 3122(用于git clone ssh://git@服务器:3122/...)。若这两个端口被占用,改冒号左侧即可,同时记得同步修改安装向导里的 SSH 端口(见第五章)。depends_on: db:保证启动顺序先数据库后 Forgejo(只控制启动顺序,不等待数据库「就绪」,所以 Forgejo 首次启动若数据库还没就绪会自动重连,属正常现象)。restart: unless-stopped:两个服务都开机自启、异常退出自动拉起,除非手动 stop。networks: forgejo-net (driver: bridge):自定义 bridge 网络,让两个服务在同一内网且能用容器名互访。
💡 技术拓展:Forgejo 的数据后端不止 PostgreSQL。
[database]段支持sqlite3、mysql、postgres三种DB_TYPE。| 后端 | 特点 | 适用场景 | |---|---|---| | sqlite3 | 单文件、零依赖、备份就是拷文件 | 个人/小团队,几十用户以内 | | mysql | 使用广泛、运维生态成熟 | 已有 MySQL 运维体系的团队 | | postgres | 并发与 JSON 能力强、Forgejo CI 大数据量下表现稳 | 中大型团队、启用 Actions 的实例 |本文因要给团队多人使用且后续启用 Forgejo Actions(CI 会产生大量任务与日志写入),采用 PostgreSQL 16。
4.2 准备 .env(数据库口令不入正文)
compose.yml 中数据库密码用 ${FORGEJO_DB_PASSWORD} 占位,实际值放在同目录 .env 文件里(Compose 会自动读取同目录 .env):
printf 'FORGEJO_DB_PASSWORD=Forgejo2026Db\n' > /opt/data/forgejo/.env
cat /opt/data/forgejo/.env
FORGEJO_DB_PASSWORD=Forgejo2026Db
Forgejo2026Db 是本文实测用的示例口令,生产环境请替换为自己的强口令并保护 .env 文件权限(chmod 600)。
4.3 启动
cd /opt/data/forgejo && docker compose up -d
实测回显(首次启动,需要创建网络与两个服务):
Network forgejo_forgejo-net Creating
Network forgejo_forgejo-net Created
Container forgejo-16-db Creating
Container forgejo-16-db Created
Container forgejo-16.0.6-devops Creating
Container forgejo-16.0.6-devops Created
Container forgejo-16-db Starting
Container forgejo-16-db Started
Container forgejo-16.0.6-devops Starting
Container forgejo-16.0.6-devops Started
4.4 确认服务状态
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
forgejo-16-db postgres:16-alpine "docker-entrypoint.s…" db 8 seconds ago Up 8 seconds 5432/tcp
forgejo-16.0.6-devops codeberg.org/forgejo/forgejo:16.0.6 "/usr/bin/entrypoint…" forgejo 8 seconds ago Up 8 seconds 0.0.0.0:3122->22/tcp, [::]:3122->22/tcp, 0.0.0.0:3100->3000/tcp, [::]:3100->3000/tcp
两个服务均为 Up,端口映射 0.0.0.0:3100->3000 与 0.0.0.0:3122->22 正确。约 10 秒后访问 Web 验证:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://localhost:3100/
HTTP 200
此时返回 200 的页面是安装向导(尚未初始化),下一步完成初始化。
五、初始化安装向导实测
5.1 打开安装页
浏览器访问 http://<服务器IP>:3100/,实测页面标题为:
curl -s http://localhost:3100/ | grep -o '<title>[^<]*</title>'
<title>Installation - Forgejo: Beyond coding. We forge.</title>
5.2 数据库设置(已预填)
因为第四章在 environment 里预置了 FORGEJO__database__* 变量,安装页「数据库设置」分组实测已自动填好以下值(从安装页 HTML 中提取的真实默认值):
| 表单项 | 实测默认值 | 说明 |
|---|---|---|
| 数据库类型 | postgres | 与 FORGEJO__database__DB_TYPE 对应 |
| 主机 | forgejo-16-db:5432 | 服务容器名 + PostgreSQL 端口 |
| 用户 | forgejo | 与 POSTGRES_USER 一致 |
| 密码 | Forgejo2026Db | 与 .env 中 FORGEJO_DB_PASSWORD 一致 |
| 数据库名 | forgejo | 与 POSTGRES_DB 一致 |
| SSL 模式 | disable | 内网直连无需 TLS |
| 表结构(Schema) | public | PostgreSQL 默认 Schema |
未配置环境变量时这些字段为空,需要手工填写——这就是推荐在 compose 里预置数据库环境变量的原因:向导页面所见即 compose 所配,避免手工输入出错。
5.3 一般设置(本文实测取值)
| 表单项 | 本文实测值 | 说明 |
|---|---|---|
| 站点名称 | Forgejo | 显示在标题栏与页脚,可随时在 app.ini 改 |
| 仓库根目录 | /data/git/repositories(默认) | 容器内路径,对应宿主 /opt/data/forgejo/forgejo/git/repositories |
| Git LFS 根目录 | /data/git/lfs(默认) | 大文件存储路径 |
| 运行用户 | git(默认) | 不要改,与镜像内置用户一致 |
| 服务器域名 | localhost | 生产填对外域名(如 git.example.com),影响 clone URL |
| SSH 端口 | 3122 | 填宿主对外端口(不是容器内 22),决定页面展示的 SSH clone URL |
| 内置服务器端口 | 3000(默认) | Forgejo 进程监听端口,不要改 |
| Forgejo 基础 URL | http://localhost:3100/ | 填 http://<对外IP或域名>:3100/,影响所有 HTTP clone URL |
| 日志根目录 | /data/gitea/log(默认) | 保持默认 |
⚠️ 「SSH 端口」与「内置服务器端口」最容易混淆:SSH 端口填的是用户实际连接时用的端口(本文 3122,即宿主映射端口),内置服务器端口是 Forgejo 进程自己在容器内监听的 22。填反了会导致页面给出的 SSH clone 地址无法连接。
「服务器域名」与「基础 URL」在实测中的效果:安装时填 localhost,仓库的 SSH clone 地址就是 ssh://git@localhost:3122/...;若填 git.example.com,实测地址变为 ssh://git@git.example.com:3122/...(第三章可复验)。
5.4 管理员账号与可选项
页面下方「管理员账号设置」分组填入:
| 表单项 | 本文实测值 |
|---|---|
| 管理员用户名 | root |
| 密码 | q1w2e3r4 |
| 确认密码 | q1w2e3r4 |
| 电子邮箱 | root@example.com |
⚠️ 若跳过此分组,安装完成后第一个注册的用户需要在首页手动点「注册」创建并提升管理员,步骤更多;生产环境务必在向导阶段就建好管理员。 ⚠️ Forgejo 默认密码策略要求至少 8 个字符,
q1w2e3r4恰好满足;最小长度可用MIN_PASSWORD_LENGTH调整(见《Forgejo 16.0 配置参数详解》)。
「可选设置」分组保持默认即可,逐项含义:禁止用户自助注册(勾选后只允许管理员建号,团队私有部署建议勾选,实测勾选后写入 [service] DISABLE_REGISTRATION = true)、要求登录才能查看代码、隐藏版本号 等都可以安装后在 app.ini 再调整。
5.5 提交安装
点击「立即安装」按钮,实测页面返回 HTTP 200 并跳转首页(用 curl 模拟完整表单提交的实测回显):
curl -s -b /tmp/forgejo-cookies.txt -m 60 -o /dev/null -w 'HTTP %{http_code}, redirect=%{redirect_url}\n' -X POST http://localhost:3100/ \
--data-urlencode 'db_type=postgres' \
--data-urlencode 'ssl_mode=disable' \
--data-urlencode 'db_host=forgejo-16-db:5432' \
--data-urlencode 'db_user=forgejo' \
--data-urlencode 'db_passwd=Forgejo2026Db' \
--data-urlencode 'db_name=forgejo' \
--data-urlencode 'db_schema=public' \
--data-urlencode 'app_name=Forgejo' \
--data-urlencode 'repo_root_path=/data/git/repositories' \
--data-urlencode 'lfs_root_path=/data/git/lfs' \
--data-urlencode 'run_user=git' \
--data-urlencode 'domain=localhost' \
--data-urlencode 'ssh_port=3122' \
--data-urlencode 'http_port=3000' \
--data-urlencode 'app_url=http://localhost:3100/' \
--data-urlencode 'log_root_path=/data/gitea/log' \
--data-urlencode 'no_reply_address=noreply.localhost' \
--data-urlencode 'password_algorithm=pbkdf2_hi' \
--data-urlencode 'admin_name=root' \
--data-urlencode 'admin_passwd=q1w2e3r4' \
--data-urlencode 'admin_confirm_passwd=q1w2e3r4' \
--data-urlencode 'admin_email=root@example.com' \
--data-urlencode 'offline_mode=on' \
--data-urlencode 'disable_registration=on'
HTTP 200, redirect=
⚠️ 安装表单只能提交一次。安装完成后 Forgejo 会在
app.ini写入[security] INSTALL_LOCK = true锁死向导,再次访问/直接进首页。若需要重装,须清空/opt/data/forgejo/forgejo与数据库后重新初始化。
5.6 安装结果验证
curl -s http://localhost:3100/api/v1/version
{"version":"16.0.6+gitea-1.22.0"}
同时确认安装向导生成的配置文件已落到宿主机持久化目录:
head -20 /opt/data/forgejo/forgejo/gitea/conf/app.ini
APP_NAME = Forgejo
RUN_MODE = prod
APP_SLOGAN =
RUN_USER = git
WORK_PATH = /data/gitea
[repository]
ROOT = /data/git/repositories
[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
[repository.upload]
TEMP_PATH = /data/gitea/uploads
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = localhost
SSH_DOMAIN = localhost
HTTP_PORT = 3000
ROOT_URL = http://localhost:3100/
这份 app.ini 就是 Forgejo 的主配置文件(逐段详解见《Forgejo 16.0 配置参数详解》),修改后重启服务生效。
六、硬性验收:建仓 + push + Issue
安装完成后按真实用户路径走一遍核心链路,三步回显均为实测输出。
6.1 创建测试仓库
用管理员 token 通过 API 建仓(Web 界面点「+」→「新建仓库」等效):
TOKEN=9576df064e16e53dbf36e8935dba86a6dd8fe381
curl -s -m 15 -X POST http://localhost:3100/api/v1/user/repos \
-H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"hello-forgejo","description":"B2 部署验收测试仓库","private":false,"auto_init":false}' \
| python3 -c "
import json,sys
r=json.load(sys.stdin)
print('id:',r.get('id'))
print('full_name:',r.get('full_name'))
print('clone_url:',r.get('clone_url'))
print('ssh_url:',r.get('ssh_url'))
print('default_branch:',r.get('default_branch'))
"
id: 1
full_name: root/hello-forgejo
clone_url: http://localhost:3100/root/hello-forgejo.git
ssh_url: ssh://git@localhost:3122/root/hello-forgejo.git
💡 说明:API 返回的
ssh_url端口是 3122——正是安装向导里「SSH 端口」填的值;说明该端口设置已生效。token 创建方法:页面右上角头像 → 设置 → 应用 → 生成新令牌,或POST /api/v1/users/root/tokens。
6.2 clone + commit + push 实测
cd /tmp && git clone http://root:q1w2e3r4@localhost:3100/root/hello-forgejo.git push-demo
Cloning into 'push-demo'...
cd push-demo && git config user.name root && git config user.email root@example.com && echo "push test" > push.txt && git add . && git commit -m "push 链路验证" && git push origin main
[main 28de242] push 链路验证
Author: root <root@example.com>
1 file changed, 1 insertion(+)
create mode 100644 push.txt
To http://localhost:3100/root/hello-forgejo.git
c945d6d..28de242 main -> main
push 成功后立刻通过 API 确认提交已落库:
curl -s -m 10 "http://localhost:3100/api/v1/repos/root/hello-forgejo/commits?limit=2" \
-H "Authorization: token $TOKEN" \
| python3 -c "import json,sys; [print(c['sha'][:10], c['commit']['message'].strip()) for c in json.load(sys.stdin)]"
28de242d46 push 链路验证
c945d6d2c7 push 链路验证
6.3 创建 Issue 实测
curl -s -m 15 -X POST http://localhost:3100/api/v1/repos/root/hello-forgejo/issues \
-H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
-d '{"title":"部署验收:push 与 Issue 功能验证","body":"B2 部署文档验收项"}' \
| python3 -c "
import json,sys
r=json.load(sys.stdin)
print('issue number:', r.get('number'))
print('title:', r.get('title'))
print('state:', r.get('state'))
print('url:', r.get('html_url'))
"
issue number: 1
title: 部署验收:push 与 Issue 功能验证
state: open
url: http://localhost:3100/root/hello-forgejo/issues/1
回查 Issue 列表确认:
curl -s -m 10 "http://localhost:3100/api/v1/repos/root/hello-forgejo/issues?state=all" \
-H "Authorization: token $TOKEN" \
| python3 -c "import json,sys; [print('#%d %s [%s]'%(i['number'],i['title'],i['state'])) for i in json.load(sys.stdin)]"
#1 部署验收:push 与 Issue 功能验证 [open]
至此「建仓 → push → Issue」三项验收全部通过,部署可交付使用。
七、数据持久化说明
部署完成后宿主机数据目录的实际结构(实测):
ls -la /opt/data/forgejo/forgejo/
total 76
drwxr-xr-x 12 yahui yahui 4096 10月 17 19:52 .
drwxrwxrwx 5 root root 4096 10月 17 11:41 ..
-rw------- 1 yahui yahui 53K 10月 17 19:52 forgejo-dump-1792237967.zip
drwxr-xr-x 18 yahui yahui 4096 10月 17 19:41 gitea
drwxr-xr-x 5 yahui yahui 4096 10月 17 19:41 git
| 宿主机路径 | 用途 | 备份价值 |
|---|---|---|
/opt/data/forgejo/forgejo/git/repositories/ | 全部仓库的裸库(owner/repo.git) | ★★★ 核心 |
/opt/data/forgejo/forgejo/gitea/conf/app.ini | 主配置文件 | ★★★ 核心 |
/opt/data/forgejo/forgejo/gitea/ 其余 | 附件、头像、LFS、Issue 索引、日志、Actions 日志 | ★★ |
/opt/data/forgejo/db/ | PostgreSQL 数据文件 | ★★★ 核心 |
⚠️ 不要只备份
/opt/data/forgejo/forgejo:Issue/PR/用户/权限元数据都在 PostgreSQL 里(/opt/data/forgejo/db)。推荐使用 Forgejo 自带的forgejo dump一键打包(含数据库 SQL 导出),流程见《Forgejo 16.0 运维手册》。
验证持久化最直接的方法是重启整个栈后确认数据仍在:
cd /opt/data/forgejo && docker compose restart
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
forgejo-16-db postgres:16-alpine "docker-entrypoint.s…" db 8 seconds ago Up 8 seconds 5432/tcp
forgejo-16.0.6-devops codeberg.org/forgejo/forgejo:16.0.6 "/usr/bin/entrypoint…" forgejo 8 seconds ago Up 8 seconds 0.0.0.0:3122->22/tcp, [::]:3122->22/tcp, 0.0.0.0:3100->3000/tcp, [::]:3100->3000/tcp
重启后 curl -s http://localhost:3100/api/v1/version 仍返回 {"version":"16.0.6+gitea-1.22.0"},仓库与 Issue 数据不丢。
八、环境变量表
Forgejo 镜像支持的常用环境变量(实测生效的已标注),均为「预置 app.ini 配置」用途,数据库相关变量在安装向导页面会被自动预填:
| 环境变量 | 写入的配置 | 示例值 | 实测效果 |
|---|---|---|---|
USER_UID / USER_GID | 进程运行身份 | 1000 | /data 文件属主为 1000,与宿主目录权限匹配(实测 ls -la 显示 yahui yahui) |
FORGEJO__database__DB_TYPE | [database] DB_TYPE | postgres | 安装页「数据库类型」预填 postgres |
FORGEJO__database__HOST | [database] HOST | forgejo-16-db:5432 | 安装页「主机」预填该值 |
FORGEJO__database__NAME | [database] NAME | forgejo | 安装页「数据库名」预填该值 |
FORGEJO__database__USER | [database] USER | forgejo | 安装页「用户」预填该值 |
FORGEJO__database__PASSWD | [database] PASSWD | ${FORGEJO_DB_PASSWORD} | 安装页「密码」预填,实际值来自 .env |
FORGEJO__server__DOMAIN | [server] DOMAIN | git.example.com | 预填服务器域名 |
FORGEJO__server__ROOT_URL | [server] ROOT_URL | https://git.example.com/ | 预填基础 URL |
FORGEJO__security__INSTALL_LOCK | [security] INSTALL_LOCK | true | 置 true 跳过安装向导(配合导入备份恢复场景) |
规则:FORGEJO__<段名>__<键名> 双下划线分隔段与键,段名小写。其余任意 app.ini 键都可用该规则注入,无需挂载配置文件。
九、配置文件挂载
除了环境变量注入,也可以直接挂载完整的 app.ini。两种方式对比:
| 方式 | 适用场景 | 做法 |
|---|---|---|
| 环境变量注入 | 少量关键项(数据库、域名、密码),向导预填 | environment: 里写 FORGEJO__段__键(本文采用) |
| 挂载配置文件 | 配置项多、需要版本化管理 app.ini | volumes: 增加 - /opt/data/forgejo/app.ini:/data/gitea/conf/app.ini |
⚠️ 两种方式同时使用时环境变量优先级更高(启动时覆盖挂载文件中的对应键)。首次部署推荐「环境变量注入 + 向导生成」;后续把生成的 /opt/data/forgejo/forgejo/gitea/conf/app.ini 纳入配置管理即可——它本身就是 bind mount 出来的宿主文件,直接可改,改完重启生效(实测流程见《Forgejo 16.0 配置参数详解》)。
十、等价 docker run 命令
不用 Compose 时,以下两条 docker run 与本文 compose.yml 完全等价(注意先手工建网络):
docker network create forgejo-net
docker run -d --name forgejo-16-db --network forgejo-net \
-e POSTGRES_USER=forgejo \
-e POSTGRES_PASSWORD=Forgejo2026Db \
-e POSTGRES_DB=forgejo \
-v /opt/data/forgejo/db:/var/lib/postgresql/data \
--restart unless-stopped \
postgres:16-alpine
docker run -d --name forgejo-16.0.6-devops --network forgejo-net \
-p 3100:3000 -p 3122:22 \
-e USER_UID=1000 -e USER_GID=1000 \
-e FORGEJO__database__DB_TYPE=postgres \
-e FORGEJO__database__HOST=forgejo-16-db:5432 \
-e FORGEJO__database__NAME=forgejo \
-e FORGEJO__database__USER=forgejo \
-e FORGEJO__database__PASSWD=Forgejo2026Db \
-v /opt/data/forgejo/forgejo:/data \
-v /etc/timezone:/etc/timezone:ro \
-v /etc/localtime:/etc/localtime:ro \
--restart unless-stopped \
codeberg.org/forgejo/forgejo:16.0.6
💡 生产仍推荐 Compose:两个服务的网络、依赖、重启策略在一个文件里声明,升级与迁移时
docker compose pull && docker compose up -d一步完成。
十一、常用运维命令
以下命令在 /opt/data/forgejo/ 目录下执行:
| 操作 | 命令 |
|---|---|
| 查看服务状态 | docker compose ps |
| 查看实时日志 | docker compose logs -f forgejo |
| 重启单个服务 | docker compose restart forgejo |
| 停止整个栈(保留数据) | docker compose down |
| 停止并删除数据卷之外的所有资源 | docker compose down --remove-orphans |
| 升级镜像(先备份!) | docker compose pull && docker compose up -d |
⚠️
docker compose down不会删除 bind mount 的宿主目录(/opt/data/forgejo/),数据安全;但千万不要对数据目录执行rm -rf来"重置"——数据库文件被删后无法恢复,重置前先做 dump。
十二、常见问题
Q1:访问 3100 端口返回的页面是英文的安装向导,但数据库报错连不上?
先确认数据库服务状态 docker compose ps 中 db 为 Up;再看日志 docker compose logs db | tail。实测中最常见的根因是 .env 未创建导致 POSTGRES_PASSWORD 与 Forgejo 侧不一致——两者必须用同一个变量值(本文统一为 ${FORGEJO_DB_PASSWORD})。
Q2:git push 时提示 The requested URL returned error: 403?
HTTP push 需要 URL 中携带账号密码(本文 http://root:q1w2e3r4@localhost:3100/...)或在客户端配置凭据。若用 token,用户名填任意非空字符串、密码填 token。403 也可能因为目标仓库为私有且凭据无写权限。
Q3:页面显示的 SSH clone 地址是 git@localhost:3122/...,同事机器上连不上?
localhost 是安装向导「服务器域名」填的值。生产改为对外域名或 IP(改 app.ini 的 [server] DOMAIN 与 SSH_DOMAIN 后重启),实测改法与效果见《Forgejo 16.0 配置参数详解》。
Q4:首次启动时 Forgejo 反复重连数据库?
depends_on 只保证启动顺序不保证就绪。PostgreSQL 首次初始化(创建目录结构)需要几秒到几十秒,Forgejo 默认重试 10 次,通常能自动追上;若日志出现 ORM engine initialization attempt #x/10 后仍失败,等数据库 Up 后 docker compose restart forgejo 即可。
Q5:想用 SQLite 快速试一下,compose 怎么改?
去掉 db 整个 service、去掉 Forgejo 的 5 个 FORGEJO__database__* 变量与 depends_on,安装向导「数据库类型」选 SQLite3、路径填 /data/gitea/forgejo.db 即可。SQLite 实测可正常完成建仓/push/Issue 验收,但多人协作与 Actions 场景建议 PostgreSQL。
十三、参考链接
- Forgejo 官方文档(安装):https://forgejo.org/docs/latest/admin/installation-docker/
- Forgejo 镜像仓库:https://codeberg.org/forgejo/forgejo
- Forgejo 16.0.6 Release:https://codeberg.org/forgejo/forgejo/releases/tag/v16.0.6
- Forgejo 配置速查(app.ini 全参数):https://forgejo.org/docs/latest/admin/config-cheat-sheet/
- Gitea 兼容文档(Forgejo 内核同源):https://docs.gitea.com/
- 本系列相关:《Forgejo 16.0 介绍与选型》《Forgejo 16.0 配置参数详解》《Forgejo 16.0 运维手册》
- 相关文档:《OneDev Docker Compose 部署指南》《Ubuntu 22.04 上用 Docker Compose 部署 n8n 2.43.7》《Kestra 2.0.6 Docker Compose 部署指南》