Fava 1.30.16 Docker Compose 部署指南

以 Ubuntu 服务器实测完成 Fava 1.30.16 的 Docker Compose 部署:社区镜像 yegle/fava 与自建锁版镜像双方案对照、账本目录持久化与重启恢复闭环、端口与环境变量配置、等价 docker run 形态,并沉淀 Entrypoint 参数报错与 BuildKit 代理拉取等常见问题排障。

Fava财务记账自托管2026/10/23

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,监听地址localhost0.0.0.0
FAVA_PORT等价于 --port,监听端口50005000

说明: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。

十二、参考链接

  1. Fava 官方文档:https://beancount.github.io/fava/
  2. Fava 源码仓库:https://github.com/beancount/fava/
  3. yegle/fava 镜像页:https://hub.docker.com/r/yegle/fava
  4. 本专栏安装篇:《Ubuntu 22.04 安装 Fava 1.30.16 指南》