Fava 1.30.16 Docker Compose 部署指南
以 Ubuntu 服务器实测完成 Fava 1.30.16 的 Docker Compose 部署:社区镜像 yegle/fava 与自建锁版镜像双方案对照、账本目录持久化与重启恢复闭环、端口与环境变量配置、等价 docker run 形态,并沉淀 Entrypoint 参数报错与 BuildKit 代理拉取等常见问题排障。
Fava 1.30.16 Docker Compose 部署指南
目标:用 Docker Compose 把 Fava 1.30.16(Beancount 复式记账 Web 界面)跑起来,完成社区镜像与自建镜像两种方案部署、账本文件挂载持久化、容器重建后的数据恢复闭环验证。全部命令与回显已在 Ubuntu 22.04 服务器(Docker 29.8.1 + Compose v2)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- Docker:29.8.1;Docker Compose:v2(
docker compose子命令形式) - 部署对象:Fava 1.30.16(2026-08-18 发布)+ Beancount 3.2.3
- 项目目录:
/opt/fava-compose/ - 端口:宿主机 5000 → 容器 5000(Fava 默认端口)
- 持久化:
./ledger目录 bind mount 到容器/ledger
二、镜像选型说明
Fava 没有 Docker 官方镜像,可选两条路线(2026-10-23 实查实测):
| 镜像 | 维护方 | 实际版本 | 优势 | 劣势 |
|---|---|---|---|---|
yegle/fava:v1.30 | 社区(跟随上游自动构建) | 实测镜像内 fava --version 为 1.30.4 | 开箱即用、体积小(拉取约 50MB 压缩层) | 版本滞后于 PyPI 最新稳定版,tag 粒度为次版本号(v1.30 ≠ 1.30.16) |
自建 python:3.12-slim + pip install fava==1.30.16 | 自己维护 | 精确锁定 1.30.16 | 版本可控、可加装 excel 导出 extra、可预置导入器依赖 | 需维护 Dockerfile,升级时重新构建 |
💡 说明:Docker Hub 上 yegle/fava 的
latest与v1.30标签同指 1.30.4(标签更新时间 2025-07-06 实查)。本文两种方案都完整给出:快速验证用社区镜像,生产环境建议自建镜像锁版本。两方案容器内启动命令完全一致。
三、前置条件
docker --version
docker compose version
实测输出:
Docker version 29.8.1, build 4a63305
Docker Compose version v2.39.4
准备项目目录结构(账本文件先在宿主机就绪):
mkdir -p /opt/fava-compose/ledger
cat > /opt/fava-compose/ledger/example.beancount <<'EOF'
option "title" "个人复式记账示例账本"
option "operating_currency" "CNY"
2026-01-01 open Assets:Bank:Card
2026-01-01 open Assets:Cash
2026-01-01 open Expenses:Food
2026-01-01 open Income:Salary
2026-01-01 open Equity:Opening-Balances
2026-01-10 * "公司" "1 月工资"
Income:Salary -15000.00 CNY
Assets:Bank:Card
2026-01-12 * "超市" "周末采购"
Expenses:Food 386.50 CNY
Assets:Bank:Card
EOF
账本语法与校验细节见安装篇(文末参考链接);账本文件放在宿主机 bind mount 目录,是后续持久化与恢复闭环的根基。
四、方案一:社区镜像部署(yegle/fava)
4.1 编写 docker-compose.yml
cat > /opt/fava-compose/docker-compose.yml <<'EOF'
name: fava-1-30-16-stack
services:
fava:
image: yegle/fava:v1.30
container_name: fava-1-30-16-web
ports:
- "5000:5000"
volumes:
- ./ledger:/ledger
command: -H 0.0.0.0 -p 5000 /ledger/example.beancount
restart: unless-stopped
EOF
配置逐项说明:name: fava-1-30-16-stack 是 Compose 项目名,多套 Fava 栈并存时避免同名项目互相覆盖;command 是纯参数——该镜像的 ENTRYPOINT 就是 fava(docker inspect 实测 Entrypoint=[fava] Cmd=[]),所以不能再在 command 里写 fava 前缀;./ledger:/ledger 把宿主机账本目录挂进容器;-H 0.0.0.0 必须显式声明,否则 fava 默认只监听容器内 localhost,端口映射后外部依然访问不到;restart: unless-stopped 保证宿主机重启后服务自动拉起。
4.2 启动与状态确认
cd /opt/fava-compose
docker compose up -d
docker compose ps
实测输出:
Container fava-1-30-16-web Started
NAME STATUS
fava-1-30-16-web Up 5 seconds
4.3 Web 验证
curl -s -o /dev/null -w "root %{http_code}\n" http://127.0.0.1:5000/
curl -sL -o /dev/null -w "page %{http_code}\n" "http://127.0.0.1:5000/%E4%B8%AA%E4%BA%BA%E5%A4%8D%E5%BC%8F%E8%AE%B0%E8%B4%A6%E7%A4%BA%E4%BE%8B%E8%B4%A6%E6%9C%AC/income_statement/"
docker exec fava-1-30-16-web fava --version
实测输出:
root 302
page 200
fava, version 1.30.4
根路径 302、账本报表页 200 即部署成功(URL 中的转义串是账本标题「个人复式记账示例账本」的 URL 编码)。确认镜像内实际版本为 1.30.4——这正是社区镜像与最新稳定版 1.30.16 的差距,对版本敏感时用方案二。
五、方案二:自建镜像部署(锁版本 1.30.16)
5.1 编写 Dockerfile
cat > /opt/fava-compose/Dockerfile <<'EOF'
FROM python:3.12-slim
RUN pip install --no-cache-dir fava==1.30.16
EXPOSE 5000
ENTRYPOINT ["fava"]
CMD ["-H", "0.0.0.0", "-p", "5000"]
EOF
逐项说明:基础镜像用 python:3.12-slim(满足 Fava ≥3.10 要求的轻量底座);pip install fava==1.30.16 精确锁定版本并自动带上 beancount 3.2.3 依赖;ENTRYPOINT ["fava"] 与社区镜像行为对齐,CMD 提供默认参数、compose 的 command 可整体覆盖;需要 Excel 导出时把安装行改为 RUN pip install --no-cache-dir "fava[excel]==1.30.16"。
5.2 编写 docker-compose.yml(自建镜像版)
cat > /opt/fava-compose/docker-compose.yml <<'EOF'
name: fava-1-30-16-stack
services:
fava:
build:
context: .
image: fava:1.30.16
container_name: fava-1-30-16-web
ports:
- "5000:5000"
volumes:
- ./ledger:/ledger
environment:
BEANCOUNT_FILE: /ledger/example.beancount
command: -H 0.0.0.0 -p 5000
restart: unless-stopped
EOF
与方案一的区别:build: context: . 声明用当前目录 Dockerfile 构建,image: fava:1.30.16 给构建产物命名;environment 注入 BEANCOUNT_FILE 环境变量后,command 不必再写账本路径——Fava 原生支持该变量(官方帮助:命令行参数可用 FAVA_ 前缀环境变量等价传递,账本文件亦可由 BEANCOUNT_FILE 指定)。
5.3 构建并启动
cd /opt/fava-compose
docker compose up -d --build
docker compose ps
实测输出(尾部):
Image fava:1.30.16 Built
Container fava-1-30-16-web Started
NAME IMAGE STATUS
fava-1-30-16-web fava:1.30.16 Up 4 seconds
5.4 Web 验证
curl -s -o /dev/null -w "root %{http_code}\n" http://127.0.0.1:5000/
curl -sL -o /dev/null -w "page %{http_code}\n" "http://127.0.0.1:5000/%E4%B8%AA%E4%BA%BA%E5%A4%8D%E5%BC%8F%E8%AE%B0%E8%B4%A6%E7%A4%BA%E4%BE%8B%E8%B4%A6%E6%9C%AC/income_statement/"
docker exec fava-1-30-16-web fava --version
实测输出:
root 302
page 200
fava, version 1.30.16
版本精确为 1.30.16,与 PyPI 最新稳定版一致。
六、数据持久化说明
Fava 与 Beancount 不使用数据库,全部数据就是账本文件本身,因此本方案的持久化等式非常简单:容器可随意销毁,账本在宿主机 /opt/fava-compose/ledger/。
- 账本文件变更:直接编辑宿主机文件,Fava 的 watchfiles 监听会感知并自动重载(网页端刷新即可见);
- 备份:备份
/opt/fava-compose/ledger/目录(建议纳入 git); - 迁移:拷贝整个
/opt/fava-compose/目录到新服务器,docker compose up -d即完成迁移。
验证"容器销毁数据不丢":
docker compose down
ls ledger/
docker compose up -d
sleep 4
curl -sL -o /dev/null -w "恢复后 HTTP %{http_code}\n" "http://127.0.0.1:5000/%E4%B8%AA%E4%BA%BA%E5%A4%8D%E5%BC%8F%E8%AE%B0%E8%B4%A6%E7%A4%BA%E4%BE%8B%E8%B4%A6%E6%9C%AC/income_statement/"
实测输出:
Network fava-1-30-16-stack_default Removed
example.beancount
Container fava-1-30-16-web Started
恢复后 HTTP 200
down 删除容器后账本文件原样保留在宿主机,重新 up -d 服务恢复、报表页 200——持久化与恢复闭环验证通过。
七、环境变量表
| 变量 | 作用 | 默认值 | 示例 |
|---|---|---|---|
BEANCOUNT_FILE | 指定加载的账本文件路径(多个用 : 分隔) | 无 | /ledger/example.beancount |
FAVA_HOST | 等价于 --host,监听地址 | localhost | 0.0.0.0 |
FAVA_PORT | 等价于 --port,监听端口 | 5000 | 5000 |
说明:Fava 官方帮助明确"命令行选项都可用 FAVA_ 前缀环境变量等价设置(如 --host=0.0.0.0 等价于 FAVA_HOST=0.0.0.0)"。容器内起服时 BEANCOUNT_FILE + FAVA_HOST/FAVA_PORT 组合可以完全替代 command 参数,两种写法实测均可用。
八、配置参数说明与账本挂载
- fava 启动参数在容器里的传递路径:compose
command:字段(ENTRYPOINT 为 fava 时传纯参数),或第七节环境变量。 - 账本级配置:界面语言、默认页等写在账本文件的
custom "fava-option"指令里(如2026-01-01 custom "fava-option" "language" "zh"),随./ledger挂载进容器即生效,无需改镜像。 - 配置文件挂载:如需导入器配置(import_config)、多账本 include,把相关 Python/账本文件一并放入宿主机
ledger/目录即可,路径在容器内统一是/ledger/...。 - 反向代理建议:Fava 无内置认证,生产环境务必在前置 Nginx/Caddy 加 Basic Auth 或 OAuth2 Proxy,并通过
proxy_set_header Host $host;保持 Fava 生成的链接正确。
九、等价 docker run 命令
与第五节 compose 等价的裸 docker run:
docker run -d \
--name fava-1-30-16-web \
-p 5000:5000 \
-v /opt/fava-compose/ledger:/ledger \
-e BEANCOUNT_FILE=/ledger/example.beancount \
--restart unless-stopped \
fava:1.30.16 -H 0.0.0.0 -p 5000
多账本加载(Fava 支持一个实例挂多本账,页面右上角切换):
docker run -d --name fava-1-30-16-multi \
-p 5000:5000 -v /opt/fava-compose/ledger:/ledger \
--restart unless-stopped \
fava:1.30.16 -H 0.0.0.0 -p 5000 /ledger/example.beancount /ledger/second.beancount
十、常用运维命令
cd /opt/fava-compose
docker compose ps # 服务状态
docker compose logs -f fava # 跟踪日志(启动行:Starting Fava on http://0.0.0.0:5000)
docker compose restart fava # 重启服务
docker compose down # 停止并删除容器(账本在宿主机不受影响)
docker compose up -d --build # 修改 Dockerfile 后重建升级
实测启动日志:
Starting Fava on http://0.0.0.0:5000
升级到新版本(自建镜像方案):改 Dockerfile 中的版本号 → docker compose up -d --build;社区镜像方案:docker compose pull fava && docker compose up -d。回滚即把版本号改回旧值重新 build。
十一、常见问题(FAQ)
Q1:容器反复重启,日志报 Invalid value for '[FILENAMES]...': File 'fava' does not exist?
镜像 ENTRYPOINT 已是 fava,compose 的 command 又写了一遍 fava -H ...,实际执行变成 fava fava -H ...,把 "fava" 当账本文件名。实测报错原文:
Error: Invalid value for '[FILENAMES]...': File 'fava' does not exist.
解法:command 只写参数(-H 0.0.0.0 -p 5000 /ledger/example.beancount)。
Q2:容器内 fava 已启动、端口也映射了,宿主机访问不通?
启动参数少了 -H 0.0.0.0。fava 默认监听 localhost(容器内回环),端口映射转发不到。确认 command 或 CMD 里有 -H 0.0.0.0。
Q3:拉取镜像慢或超时?
为 Docker 守护进程配置镜像/代理(/etc/docker/daemon.json 的 proxies 字段或国内 registry mirror),systemctl restart docker 后重试 docker compose pull。
Q4:自建镜像构建时拉不到 python:3.12-slim 基础镜像?
构建器的令牌请求不走守护进程代理。先 docker pull python:3.12-slim(走守护进程代理)把基础镜像落到本地,再执行 docker compose up -d --build 即可复用本地镜像。
Q5:Fava 网页能开但账本里出现报错横幅?
账本语法问题(复式不平衡、指令错误)会在页面顶部红条与 Errors 列表展示,与容器部署无关。先用命令行定位:docker exec fava-1-30-16-web bean-check /ledger/example.beancount。
十二、参考链接
- Fava 官方文档:https://beancount.github.io/fava/
- Fava 源码仓库:https://github.com/beancount/fava/
- yegle/fava 镜像页:https://hub.docker.com/r/yegle/fava
- 本专栏安装篇:《Ubuntu 22.04 安装 Fava 1.30.16 指南》