OpenBudgeteer Docker Compose 部署指南

OpenBudgeteer 1.11.2 Docker Compose 从零部署实战:Web+API+MariaDB+Redis 四服务编排、首次启动日志、持久化与备份、升级与常见问题排障,全部命令与回显实测(2026-10-24)。

OpenBudgeteer财务记账自托管Docker Compose安装部署2026/10/24

OpenBudgeteer Docker Compose 部署指南

目标:在一台 Ubuntu 22.04 服务器上,用 Docker Compose 从零部署 OpenBudgeteer 1.11.2(Web 前端 + MariaDB + Redis + 可选 API 服务),完成启动、验证、数据持久化、备份与升级全流程。本文全部命令与回显在 Docker 29.8.1 + Compose v5.5.1 环境实测通过(2026-10-24)。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Docker:29.8.1(docker version 实测:Docker 29.8.1 (api 1.56))
  • Docker Compose:v5.5.1(docker compose version 实测:Docker Compose version v5.5.1)
  • OpenBudgeteer:1.11.2(镜像 axelander/openbudgeteer:1.11.2,2026-10-23 发布,为当前最新稳定版)
  • API 镜像:axelander/openbudgeteer-api:latest(与 1.11.2 同日更新;该镜像只有 latest 与 pre-release 两个标签)
  • 依赖服务:MariaDB 11.8(mariadb:11.8)、Redis 8.2(redis:8.2)
  • 部署目录:/opt/openbudgeteer/
  • 端口规划:Web 8080(应用内置监听 8080)、API 8082
  • 数据库依赖链:MariaDB/MySQL 或 PostgreSQL 二选一 + Redis 强制(v1.10 起 Redis 为必需组件;SQLite 已在 v1.8.3 被移除,官方 Install 页 "Database & Redis" 一节明确 "OpenBudgeteer requires a connection to a database and to Redis")

二、镜像选型说明

OpenBudgeteer 官方只通过 Docker Hub 分发预构建镜像,无发行版软件包。选型对照(Docker Hub 2026-10-24 实查):

镜像标签用途说明
axelander/openbudgeteer1.11.2Web 前端(推荐)按版本锁定的稳定标签,生产环境首选
axelander/openbudgeteerlatestWeb 前端跟随最新稳定版,官方 Quick Start 使用
axelander/openbudgeteerpre-releaseWeb 前端预发布尝鲜,官方文档注明 "can contain bugs on web frontend and also on database side"
axelander/openbudgeteer-apilatest / pre-releaseREST API 服务无版本号标签,与主镜像同期更新

镜像体积:主镜像压缩层约 94.2 MB(解压后约 347 MB),API 镜像约 66.3 MB(解压后约 226 MB),均基于 ASP.NET 运行时。主镜像内置声明端口 8080(当前监听端口,.NET 8 默认)与 8081(历史版本默认端口,仅作兼容声明,无需映射)。

选择建议:生产环境用 1.11.2 这样的版本标签锁定,升级时显式改标签;体验新功能再考虑 pre-release。不要混用 latest 与 pre-release——pre-release 可能包含数据库 schema 变更,回退有风险。

三、前置条件

  1. 服务器已安装 Docker Engine 24+ 与 Docker Compose v2 插件(docker compose version 可执行);
  2. 服务器可访问 Docker Hub 拉取镜像(内网环境需预先导入镜像或配置镜像加速);
  3. 端口 8080(Web)、8082(API,可选)未被占用,检查命令与实测回显:
ss -ltn | grep -E ':(8080|8082)\b'

无输出即表示两个端口均空闲(本文实测环境该命令无输出)。

  1. 磁盘空间 ≥ 1 GB(镜像约 600 MB + 数据库数据);
  2. 若使用外部已有 MariaDB/PostgreSQL 与 Redis,可省略下文对应的 service,只保留应用容器并指向外部地址。

四、部署步骤

4.1 准备部署目录与 Compose 文件

创建部署目录并写入 docker-compose.yml。以下配置在官方 Quick Start(MariaDB + Redis 组合)基础上做了三点工程化补强:显式 Compose 项目名(避免与其他项目同名冲突)、固定版本标签、API 服务一起部署:

mkdir -p /opt/openbudgeteer && cd /opt/openbudgeteer
# /opt/openbudgeteer/docker-compose.yml
name: openbudgeteer-1.11.2-stack

services:
  openbudgeteer:
    image: axelander/openbudgeteer:1.11.2
    container_name: openbudgeteer
    ports:
      - "8080:8080"
    environment:
      - CONNECTION_PROVIDER=mariadb
      - CONNECTION_SERVER=openbudgeteer-mariadb
      - CONNECTION_PORT=3306
      - CONNECTION_DATABASE=openbudgeteer
      - CONNECTION_USER=openbudgeteer
      - CONNECTION_PASSWORD=q1w2e3r4
      - CONNECTION_ROOT_PASSWORD=q1w2e3r4
      - CONNECTION_REDIS_SERVER=openbudgeteer-redis
      - APPSETTINGS_CULTURE=en-US
      - APPSETTINGS_DEMO_DATA=true
    depends_on:
      - mariadb
      - redis

  openbudgeteer-api:
    image: axelander/openbudgeteer-api:latest
    container_name: openbudgeteer-api
    ports:
      - "8082:8080"
    environment:
      - CONNECTION_PROVIDER=mariadb
      - CONNECTION_SERVER=openbudgeteer-mariadb
      - CONNECTION_PORT=3306
      - CONNECTION_DATABASE=openbudgeteer
      - CONNECTION_USER=openbudgeteer
      - CONNECTION_PASSWORD=q1w2e3r4
    depends_on:
      - mariadb

  mariadb:
    image: mariadb:11.8
    container_name: openbudgeteer-mariadb
    environment:
      MYSQL_ROOT_PASSWORD: q1w2e3r4
      MYSQL_DATABASE: openbudgeteer
      MYSQL_USER: openbudgeteer
      MYSQL_PASSWORD: q1w2e3r4
    volumes:
      - db-data:/var/lib/mysql

  redis:
    image: redis:8.2
    container_name: openbudgeteer-redis
    volumes:
      - redis-data:/data

volumes:
  db-data:
  redis-data:

⚠️ 注意:CONNECTION_ROOT_PASSWORD 仅在"数据库用户与库尚不存在、需要 OpenBudgeteer 自行创建"时才需要(首次启动后可移除)。本文同时预置了 MYSQL_DATABASE/MYSQL_USER/MYSQL_PASSWORD 让 MariaDB 镜像建库,两种方式二选一即可;同时存在时以 MariaDB 镜像的初始化为准,OpenBudgeteer 直接使用已存在的库。

配置逐项说明:

  • name: openbudgeteer-1.11.2-stack:Compose 项目名,显式指定可避免多套部署同名互相干扰;
  • CONNECTION_PROVIDER=mariadb:数据库类型,大小写不敏感,可选 mysql/mariadb/postgres/postgresql;
  • CONNECTION_SERVER=openbudgeteer-mariadb:数据库主机名,必须是同一 Compose 网络内可达的服务名(见"十一、常见问题"第 1 条,这是最容易踩的坑);
  • APPSETTINGS_DEMO_DATA=true:首次启动灌入演示数据(账户、桶、交易),方便部署后立即看到界面效果;正式使用改为 false 并清空数据库重建;
  • APPSETTINGS_CULTURE=en-US:货币/日期/数字格式,可改 zh-CN;
  • API 服务与前端的数据库四要素(provider/server/database/user/password)必须完全一致,因为两者操作同一个库。

4.2 启动

cd /opt/openbudgeteer
docker compose up -d

实测回显(首次启动,镜像已拉取完毕后):

 Container openbudgeteer-redis Starting
 Container openbudgeteer-mariadb Starting
 Container openbudgeteer-redis Started
 Container openbudgeteer-mariadb Started
 Container openbudgeteer-web Starting
 Container openbudgeteer-api Starting
 Container openbudgeteer-web Started
 Container openbudgeteer-api Started

首次启动会先拉取镜像,docker compose up -d 的输出会包含 Pulling openbudgeteer ... Pulled 等进度行,整体耗时取决于带宽(四个镜像合计约 160 MB 压缩层)。

4.3 首次启动日志

应用启动分"等待依赖 → 自动建表 → 开始监听"三个阶段,docker compose logs openbudgeteer 实测回显:

warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/home/app/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. For more information go to https://aka.ms/aspnet/dataprotectionwarning
Waiting for database.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {640f7d3d-f54e-433b-82b4-93ecf935b113} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app

两处 warn 属正常现象:DataProtection 密钥默认存放在容器内 /home/app/.aspnet/DataProtection-Keys,重建容器后 Blazor 的页面状态加密会失效,但不影响业务数据(业务数据在 MariaDB);若介意可挂载该目录持久化。

若日志持续出现 Waiting for Redis database. 或 Waiting for database. 而不进入监听阶段,说明 Redis 或数据库不可达,排查方法见"十一、常见问题"。

4.4 验证部署

依次验证容器状态、HTTP 可达性、版本号与数据库表结构:

docker compose ps

实测回显(服务状态):

SERVICE             STATUS
openbudgeteer-api   Up 2 minutes
mariadb             Up 2 minutes
redis               Up 2 minutes
openbudgeteer       Up 2 minutes
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/

实测回显:

200
curl -s http://localhost:8080/info | grep -oE 'Version: [0-9.]+'

实测回显(Info 页头部渲染的版本串):

Version: 1.11.2

验证数据库自动建表(12 张业务表 + 1 张 EF Core 迁移记录表):

docker compose exec mariadb mariadb -uopenbudgeteer -pq1w2e3r4 openbudgeteer -e 'SHOW TABLES;'

实测回显:

Tables_in_openbudgeteer
Account
BankTransaction
Bucket
BucketGroup
BucketMovement
BucketRuleSet
BucketVersion
BudgetedTransaction
ImportProfile
MappingRule
RecurringBankTransaction
__EFMigrationsHistory

浏览器访问 http://<服务器IP>:8080 即可使用(APPSETTINGS_DEMO_DATA=true 时首页已能看到 Checking account / Savings account 两张演示账户卡片)。API 服务的验证方式与端点清单见《OpenBudgeteer 1.11.2 API 使用详解》。

五、数据持久化说明

  • 业务数据(账户/交易/桶/规则/导入配置):全部存放在 MariaDB 的 openbudgeteer 库,经 db-data 卷持久化(容器内路径 /var/lib/mysql)。这是唯一需要认真备份的数据;
  • UI 设置(配色主题等):存 Redis,经 redis-data 卷持久化(容器内路径 /data),丢失的后果仅是主题重置;
  • DataProtection 密钥:默认在容器内 /home/app/.aspnet/DataProtection-Keys,未挂载时随容器重建而丢失(见 4.3 的 warn 日志)。

持久化验证实测:docker compose down(保留卷)后重新 docker compose up -d,Account 页面数据原样保留(Checking account Balance: $1,255.70、Savings account Balance: $1,500.00),版本号与建表结构不变。

六、环境变量表

OpenBudgeteer 应用容器可识别的全部环境变量如下(官方 Configuration 页 2026-10-24 版本,含实测确认的默认值)。

数据库连接(CONNECTION_*):

变量说明默认值(MySQL/MariaDB)默认值(PostgreSQL)
CONNECTION_PROVIDER数据库类型(必填,大小写不敏感)——
CONNECTION_SERVER数据库地址(IP/FQDN)localhostlocalhost
CONNECTION_PORT数据库端口33065432
CONNECTION_DATABASE库名(≤64 字符)openbudgeteerpostgres
CONNECTION_USER数据库用户openbudgeteerpostgres
CONNECTION_PASSWORD数据库密码空空
CONNECTION_ROOT_PASSWORDroot 密码(仅 MySQL/MariaDB,用于首次自动建库建用户)空不适用

Redis 连接(v1.10 起必需):

变量说明默认值
CONNECTION_REDIS_SERVERRedis 地址—
CONNECTION_REDIS_PORTRedis 端口6379
CONNECTION_REDIS_USERRedis 用户(使用 ACL 时)—
CONNECTION_REDIS_PASSWORDRedis 密码(使用 ACL 时)—
CONNECTION_REDIS_PREFIXRedis 键前缀(使用 ACL 时)—

应用设置(APPSETTINGS_*):

变量说明默认值
APPSETTINGS_CULTURE本地化标识(BCP 47),控制货币/日期/数字格式en-US
APPSETTINGS_DEMO_DATA是否生成演示数据集false

关键解读:CONNECTION_PROVIDER 与 CONNECTION_REDIS_* 是两组最常被漏配的变量——前者配错直接启动失败,后者缺失会让应用停在 Waiting for Redis database.;APPSETTINGS_* 前缀是应用自身设置的统一命名空间,后续版本扩展的新设置项也会沿用该前缀。各变量取值细节与自动建库机制逐项实测见《OpenBudgeteer 1.11.2 配置参数详解》。

七、配置参数说明

  • 数据库初始化:应用首次启动自动建表、后续升级自动执行 schema 迁移(__EFMigrationsHistory 表记录迁移版本)。若让应用自建库(CONNECTION_ROOT_PASSWORD 方式),实测会创建同名库 openbudgeteer 与用户 openbudgeteer@%,并授予 GRANT ALL PRIVILEGES ON openbudgeteer.*;
  • PostgreSQL 变体:把 CONNECTION_PROVIDER 改为 postgres(或 postgresql),端口 5432,并按"容器即数据库"模式由 PostgreSQL 镜像的 POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB 初始化角色与空库;库名字符集限制 MySQL 系比 PostgreSQL 多一项约束(- 不允许用于 PostgreSQL);
  • Redis ACL:启用鉴权时四个 Redis 变量都要配,官方给出的 ACL 文件示例为:
user openbudgeteer-redis +@all -@dangerous +info ~openbudgeteer:* on >openbudgeteer-redis-pw

即限定用户只能操作 openbudgeteer:* 前缀的键——因此配了 ACL 时 CONNECTION_REDIS_PREFIX 必须与键模式一致(示例中为 openbudgeteer)。

八、配置文件挂载

OpenBudgeteer 支持两种等价的配置方式:环境变量(上文)与 .env 文件。官方 Configuration 页原文:"Settings can be defined via Docker environment variables or via .env file which needs to be located in the root folder of the application"——即 .env 放在应用运行目录(镜像内为 /app,与 Info 页第三方依赖清单中的 dotnet-env 库对应)。

.env 文件格式为 KEY=VALUE 每行一条,例如:

CONNECTION_PROVIDER=mariadb
CONNECTION_SERVER=192.168.1.100
CONNECTION_PORT=3306
CONNECTION_DATABASE=openbudgeteer
CONNECTION_USER=openbudgeteer
CONNECTION_PASSWORD=q1w2e3r4

源码部署(非镜像)时 .env 用法最常见;镜像部署时建议仍以 Compose 的 environment: 为准,environment: 与 .env 并存时需自行确认优先级,避免两处配置漂移。

九、等价 docker run

不使用 Compose 时,等价的单容器启动命令(假设 MariaDB 与 Redis 已独立运行于同一自定义网络 openbudgeteer-net):

docker network create openbudgeteer-net

docker run -d --name openbudgeteer \
  --network openbudgeteer-net \
  -p 8080:8080 \
  -e CONNECTION_PROVIDER=mariadb \
  -e CONNECTION_SERVER=192.168.1.100 \
  -e CONNECTION_PORT=3306 \
  -e CONNECTION_DATABASE=openbudgeteer \
  -e CONNECTION_USER=openbudgeteer \
  -e CONNECTION_PASSWORD=q1w2e3r4 \
  -e CONNECTION_REDIS_SERVER=192.168.1.101 \
  -e APPSETTINGS_CULTURE=en-US \
  axelander/openbudgeteer:1.11.2

等价 API 容器:

docker run -d --name openbudgeteer-api \
  --network openbudgeteer-net \
  -p 8082:8080 \
  -e CONNECTION_PROVIDER=mariadb \
  -e CONNECTION_SERVER=192.168.1.100 \
  -e CONNECTION_PORT=3306 \
  -e CONNECTION_DATABASE=openbudgeteer \
  -e CONNECTION_USER=openbudgeteer \
  -e CONNECTION_PASSWORD=q1w2e3r4 \
  axelander/openbudgeteer-api:latest

注意 CONNECTION_SERVER 此时指向外部数据库的真实 IP/FQDN(容器网络内的服务名仅在 Compose 编排下有效)。

十、常用运维命令

以下命令均在 /opt/openbudgeteer 目录下执行。

启停与状态:

docker compose ps          # 查看四个服务状态
docker compose stop        # 全部停止(保留容器与卷)
docker compose start       # 全部启动
docker compose restart     # 重启全部服务
docker compose down        # 停止并删除容器与网络(保留数据卷)
docker compose down -v     # 连同数据卷一起删除(危险,业务数据将丢失)

日志排查:

docker compose logs openbudgeteer        # Web 前端日志(启动/运行期)
docker compose logs openbudgeteer-api    # API 服务日志
docker compose logs -f openbudgeteer     # 持续跟踪

备份业务数据(实测 mariadb-dump 全库导出约 500 行、覆盖全部 12 张表):

docker compose exec mariadb mariadb-dump -uopenbudgeteer -pq1w2e3r4 openbudgeteer > openbudgeteer-backup.sql

实测回显(文件头):

/*M!999999\- enable the sandbox mode */
-- MariaDB dump 10.20-11.8.9-MariaDB, for debian-linux-gnu (x86_64)
--
-- Host: localhost    Database: openbudgeteer
-- ------------------------------------------------------
-- Server version       11.8.9-MariaDB-ubu2404

恢复:

docker compose exec -T mariadb mariadb -uopenbudgeteer -pq1w2e3r4 openbudgeteer < openbudgeteer-backup.sql

升级流程(跨小版本前先读官方 Releases 页的 Breaking Changes):

# 1. 备份(见上)
# 2. 修改 docker-compose.yml 中的镜像标签,如 1.11.2 -> 下一版本
# 3. 拉取新镜像并滚动重建
docker compose pull
docker compose up -d
# 4. 观察启动日志确认数据库迁移自动完成,再验证 /info 页版本串

schema 迁移无需手工干预:官方 Config 页明确 "Database schema changes after an update will be also applied automatically",__EFMigrationsHistory 表即迁移记录。

卸载:

docker compose down -v     # 删除容器、网络与数据卷
rm -rf /opt/openbudgeteer  # 删除部署目录

十一、常见问题

Q1:日志一直刷 Waiting for Redis database. 不启动?

原因:CONNECTION_REDIS_SERVER 指向的主机名在 Compose 网络内不可达(本文实测踩坑:写成 openbudgeteer-redis 而实际服务名/容器名不匹配时,应用会无限重试)。定位方法:进应用容器确认解析与连通性——

docker compose exec openbudgeteer getent hosts openbudgeteer-redis

无输出即解析失败。修正 CONNECTION_REDIS_SERVER 为 docker compose ps 里显示的服务名,重新 docker compose up -d(改过 environment 需 --force-recreate)。

Q2:日志卡在 Waiting for database.?

同样是连接问题:数据库容器未就绪、CONNECTION_SERVER 拼写错误、或用户/密码与数据库实际授权不符。先 docker compose logs mariadb 确认数据库自身就绪(mariadbd 正常启动),再核对四要素。注意 depends_on 只保证启动顺序,不保证数据库完成初始化,应用的重试机制会自动等待。

Q3:访问 8081 端口不通?

镜像元数据同时声明了 8080 与 8081 两个端口,但当前版本应用实际监听 8080——v1.8 官方 Release Notes 明确 "Docker Image now listens on port 8080 (new .Net 8 default)"。8081 是镜像遗留的声明端口,并无服务监听,映射 8080:8080 即可,无需映射 8081。

Q4:演示数据能删吗?

能。演示数据(APPSETTINGS_DEMO_DATA=true 生成)就是普通业务数据。正式启用前推荐:备份数据库 → docker compose down → 清空 db-data 卷(docker volume rm)→ 把 APPSETTINGS_DEMO_DATA 改为 false → 重新 up -d,得到干净的空库。

Q5:pre-release 镜像能直接升级覆盖正式数据吗?

不建议。官方 Install 页明确 pre-release "can contain bugs on web frontend and also on database side",即数据库 schema 也可能处于过渡状态,一旦自动迁移执行、回退旧版可能失败。尝鲜请用独立数据库实例。

十二、参考链接