Mealie 3.30.0 Docker Compose 部署指南
Mealie v3.30.0 Docker Compose 部署实测:SQLite 单服务与 PostgreSQL 双服务两套 compose 全文、首次启动日志五段逐行解读(gosu 降权/62 步 alembic 迁移/默认用户初始化/APP SETTINGS dump/dual-stack 监听)、部署后验证闭环、docker run 等价形态、数据卷布局与 healthcheck 机制、7 条实测排障。
Mealie 3.30.0 Docker Compose 部署指南
目标:把 Mealie v3.30.0 用 Docker Compose 跑起来——SQLite 单服务形态与 PostgreSQL 双服务形态各一套可直接抄用的 compose,逐行解读首次启动日志(降权、迁移、初始化、配置 dump),并给出部署后验证、docker run 等价形态与常见排障。本文全部命令与日志均为本地实测回显(实测日期 2026-11-02),非官方文档转述。配置项逐项详解见本专栏《Mealie 3.30.0 配置参数详解》,API 与备份运维见《Mealie 3.30.0 常用 CLI 命令与工具详解》。
一、环境信息
本次实测的宿主机与镜像信息:
- 镜像:
ghcr.io/mealie-recipes/mealie:v3.30.0(解包体积约 1.47GB,内含 NLTK 模型与前端构建产物) - 镜像内版本指纹:
GIT_COMMIT_HASH=9552df62118224a377d9c9b0a62706a62220ab86(首次启动 APP SETTINGS dump 实测),容器内 Python 3.14.8 - 配套数据库镜像:
postgres:17(实测 dump 头部版本17.11 (Debian)) - 后端监听:容器内 9000/tcp(
API_PORT默认值,官方明确 Docker 形态下不要改) - 实测实例:
- PostgreSQL 形态:
mealie-3.30.0-app(:8152)+mealie-3.30.0-db(postgres:17,不对外发布端口) - SQLite 形态:
mealie-3.30.0-sqlite(:8157,单服务) - docker run 一次性验证实例::8160(验证后已清理)
- PostgreSQL 形态:
- 数据卷:PG 形态映射
/app/data,PG 数据另存pgdata卷;SQLite 形态映射/app/data为宿主机目录
二、部署形态选择:SQLite 还是 PostgreSQL
Mealie 数据库引擎二选一(DB_ENGINE,默认 sqlite):
| 维度 | SQLite(默认) | PostgreSQL |
|---|---|---|
| compose 服务数 | 1 个 | 2 个(+postgres) |
| 配置成本 | 零配置,库文件落在 data/mealie.db | 需配 DB_ENGINE=postgres 与 POSTGRES_* 四件套 |
| 模糊搜索 | 不可用 | 可用(官方明确仅 PG 启用;迁移日志中对应 b3dbb554ba53, postgres fuzzy search 一步,库内实测有 pg_trgm 扩展) |
| 并发 | 单写者;高并发可开 SQLITE_MIGRATE_JOURNAL_WAL=true(默认 False) | 多连接并发,官方建议 1-20 用户以上规模使用 |
| 备份工具 | 冷拷贝 mealie.db 或应用内备份 | pg_dump/pg_restore 或应用内备份 |
结论:家庭单实例、无模糊搜索诉求 → SQLite;多人使用、需要模糊搜索、已有 PG 运维习惯 → PostgreSQL。两种形态下文都给出实测 compose。
三、SQLite 形态:单服务部署(实测)
3.1 compose 文件全文
name: mealie-3.30.0-sqlite
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.30.0
container_name: mealie-3.30.0-sqlite
restart: always
ports:
- "8157:9000"
volumes:
- /opt/data/quzuo/tmp/mealie/sqlite-data:/app/data
environment:
PUID: 1000
PGID: 1000
TZ: Asia/Shanghai
BASE_URL: http://127.0.0.1:8157
ALLOW_SIGNUP: "false"
要点:
PUID/PGID:容器默认以 UID/GID 911 运行(官方默认值);宿主机数据目录属主不是 911 时显式对齐(本例 1000),否则data/写不进去。TZ:官方默认 UTC,不设则日期错位;实测设为Asia/Shanghai后,日志中每日任务排期正确换算(DAILY_SCHEDULE_TIME: 23:45本地时间 → 日志Daily tasks scheduled for 2026-11-02 15:45:00+00:00,即 23:45 CST 的 UTC 表示)。ALLOW_SIGNUP: "false":v1.4.0 起官方默认即 false(匿名注册关闭),显式写出以防误改。BASE_URL:通知与 OIDC 回调用的外部地址,单机测试写http://127.0.0.1:<端口>即可。
3.2 启动
docker compose up -d
约 15 秒后健康检查通过(docker ps 显示 Up (healthy)),curl -s http://127.0.0.1:8157/api/app/about 返回 200 且 "version": "v3.30.0"。SQLite 形态首次启动日志中可见 "DB_ENGINE": "sqlite"——不设任何 DB_* 变量时缺省即 SQLite。
四、PostgreSQL 形态:双服务部署(实测)
4.1 compose 文件全文
name: mealie-3.30.0-stack
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.30.0
container_name: mealie-3.30.0-app
restart: always
ports:
- "8152:9000"
volumes:
- /opt/data/quzuo/tmp/mealie/data:/app/data
environment:
PUID: 1000
PGID: 1000
TZ: Asia/Shanghai
BASE_URL: http://127.0.0.1:8152
ALLOW_SIGNUP: "false"
HTTP_ALLOW_LIST: 10.89.56.0/24
DB_ENGINE: postgres
POSTGRES_USER: mealie
POSTGRES_PASSWORD: mealie
POSTGRES_SERVER: postgres
POSTGRES_PORT: 5432
POSTGRES_DB: mealie
depends_on:
postgres:
condition: service_healthy
networks:
- mealie-net
postgres:
container_name: mealie-3.30.0-db
image: postgres:17
restart: always
volumes:
- /opt/data/quzuo/tmp/mealie/pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: mealie
POSTGRES_USER: mealie
PGUSER: mealie
POSTGRES_DB: mealie
healthcheck:
test: ["CMD", "pg_isready"]
interval: 30s
timeout: 20s
retries: 3
networks:
- mealie-net
networks:
mealie-net:
driver: bridge
ipam:
config:
- subnet: 10.89.56.0/24
要点:
DB_ENGINE: postgres+POSTGRES_SERVER: postgres(compose 服务名即容器内 DNS 名)。POSTGRES_*四件套的官方默认值恰好是mealie/mealie/postgres/5432/mealie,与 postgres 镜像侧对齐即可连通;生产环境务必改密码,或用POSTGRES_PASSWORD_FILE走 Docker Secrets(见配置篇)。depends_on.postgres.condition: service_healthy:必须配合 postgres 服务自定义pg_isready健康检查。Mealie 启动时数据库连接失败会直接终止(Database connection established.是迁移的前置日志),仅depends_on服务名而不等就绪,冷启动时 PG 尚未 accept 连接会导致 Mealie 重启一轮才成功。HTTP_ALLOW_LIST: 10.89.56.0/24:本例为 URL 抓取导入闭环测试专门放行内网网段——Mealie 默认拦截服务端发起的对私网/内网地址的请求(SSRF 防护),要让"贴内网 URL 导入食谱"成功,必须把目标网段加进该白名单。纯公网使用可不设。- PG 实例不发布任何宿主机端口,仅通过
mealie-net内部网络访问。
4.2 首次启动日志逐段解读(实测全文见取证)
docker compose up -d && docker logs -f mealie-3.30.0-app 从冷启动到就绪的完整日志分五段:
① 降权切用户(entrypoint run.sh 行为):
Switching to dedicated user
User uid: 1000
User gid: 1000
容器以 root 启动时,run.sh 用 gosu 切换到 PUID/PGID 指定的用户再重新执行自身,并先 chown -R $PUID:$PGID /app。
② 连接数据库并跑 alembic 迁移:
INFO ... - start: database initialization
INFO ... - Database connection established.
INFO ... - Context impl PostgresqlImpl.
INFO ... - Will assume transactional DDL.
INFO ... - Migration needed. Performing migration...
INFO ... - Running upgrade -> 6b0f5f32d602, Initial tables
...
INFO ... - Running upgrade afdc42353aa4 -> a9f823e9e441, 'add end_date to group meal plans'
INFO ... - Running upgrade a9f823e9e441 -> 071e03b4f851, 'backfill missing ai provider settings'
空库一次跑完 62 个 alembic upgrade 步骤(从 Initial tables 到 head 071e03b4f851),另有 3 个数据级迁移(Running new model migration (migrate_recipe_last_made_to_household) 等,v2 引入 Household 隔离层时的数据搬迁)。其中 b3dbb554ba53, postgres fuzzy search 这一步即 PG 专属模糊搜索的落库动作。整个迁移在 1 秒内完成(日志时间戳 02:30:12 → 02:30:13)。
③ 初始化默认数据:
INFO ... - Database contains no users, initializing...
INFO ... - Generating Default Group and Household
INFO ... - Generating Default User
INFO ... - end: database initialization
空库首次启动自动创建默认 Group(DEFAULT_GROUP=Home)、Household(DEFAULT_HOUSEHOLD=Family)与默认用户 changeme@example.com / MyPassword。这就是官方文档标注的首登凭据,也是公网部署的最大风险点(见第八节)。
④ 打印全量生效配置:
INFO ... - ------APP SETTINGS------
INFO ... - {
"LOG_LEVEL": "info",
"BASE_URL": "http://127.0.0.1:8152",
"HOST_IP": "*",
"API_PORT": 9000,
"TOKEN_TIME": 48,
"ALLOW_SIGNUP": false,
"DB_ENGINE": "postgres",
"DAILY_SCHEDULE_TIME": "23:45",
"GIT_COMMIT_HASH": "9552df62118224a377d9c9b0a62706a62220ab86",
...(全量 90+ 键,含 theme/branding/SMTP/LDAP/OIDC/AI 各分组)
}
这份 dump 是核对"环境变量到底生效没有"的最快手段——每个变量的最终值都在,逐项含义见配置篇。随后是 APP FEATURES 段,逐一判定 SMTP/LDAP/OIDC 是否可用并给出原因(如 SMTP ... Reason: Missing required values for ['SMTP_HOST', 'SMTP_FROM_EMAIL'])。
⑤ 就绪:
INFO ... - Application startup complete.
INFO ... - Uvicorn running on socket ('::', 9000, 0, 0) (Press CTRL+C to quit)
注意监听地址是 ('::', 9000)——官方文档说明:API_HOST 缺省为空时开一个 IPv6 dual-stack socket,同一端口同时接受 IPv4/IPv6;仅当宿主机不支持 dual-stack 时才回退 IPv4 0.0.0.0。
五、部署后验证闭环(实测)
按以下顺序验证,全部通过即部署成功:
- 存活:
curl -s http://127.0.0.1:8152/api/app/about→ 200,返回体含"version": "v3.30.0"(该路径即容器健康检查探针,见第七节)。 - 登录:
POST /api/auth/token(form 表单username=changeme@example.com&password=MyPassword)→ 200,返回access_token(JWT,exp为签发后TOKEN_TIME=48小时)。 - 写路径:携带 Bearer token
POST /api/recipes创建食谱 → 201 返回 slug(实测"fan-qie-chao-dan");GET /api/recipes可列出。 - 立即改密:登录后第一件事修改默认用户密码。改密后旧密码登录返回 401——实测在 PG 实例上复现:改密后再用
changeme/MyPassword请求 token 返回{"detail":"Unauthorized"},证明密码修改真实生效、旧凭据已失效。
六、docker run 等价形态(实测)
不想写 compose 时,单条 docker run 即可拉起 SQLite 形态(一次性实例 :8160 实测,验证后已清理):
docker run -d --name mealie-runtest -p 8160:9000 \
-v /opt/data/quzuo/tmp/mealie/runtest-data:/app/data \
-e BASE_URL=http://127.0.0.1:8160 \
-e ALLOW_SIGNUP=false \
-e TZ=Asia/Shanghai \
ghcr.io/mealie-recipes/mealie:v3.30.0
实测时间线:启动约 15 秒后 /api/app/about 返回 200 且 version v3.30.0;日志依次出现 Generating Default Group and Household、Generating Default User,APP SETTINGS 中 "DB_ENGINE": "sqlite"(缺省即 SQLite,无需任何 DB 变量);用默认凭据登录拿到 token(长度 224),POST /api/recipes 返回 201(slug runtest-bi-huan-yan-zheng)。compose 与 docker run 在镜像行为上完全等价,compose 只是把端口/卷/环境固化下来。
七、数据卷与健康检查机制
7.1 /app/data 卷实测布局
data/
├── .secret # 64B,JWT 签名密钥;丢失=所有已发 token 失效
├── .session_secret # 64B,会话密钥
├── mealie.log # 应用日志(同时输出到 stdout)
├── mealie.db # 仅 SQLite 形态:库文件实测 1.5MB / 70 张表
├── backups/ # 应用内备份 zip(命名 mealie_v3.30.0_<UTC时间戳>.zip)
├── recipes/ # 按食谱 UUID 分目录存图片/附件
├── users/ # 用户头像
├── groups/ # 组级资源(如 cookbook 模板)
├── templates/ # 食谱模板
└── .temp/ # 临时下载/导入缓存
两个关键认知:① .secret 持久化在数据卷内,实测容器重建(compose recreate)后旧 access_token 仍然有效;② 备份 zip 文件名用 UTC 时间戳——实测 02:37(CST)生成的备份名为 mealie_v3.30.0_2026.11.01.18.37.37.zip,核对时间注意 +8 小时。
7.2 健康检查
镜像内置 healthcheck.sh(实测全文):
#!/bin/bash
PORT="${API_PORT:-9000}"
if [ -n "$TLS_CERTIFICATE_PATH" ] && [ -n "$TLS_PRIVATE_KEY_PATH" ]; then
PROTO="https"
else
PROTO="http"
fi
# -k: TLS certificate is likely not issued for 127.0.0.1, so don't verify
curl -fsk "${PROTO}://127.0.0.1:${PORT}/api/app/about" > /dev/null
即探针就是 GET /api/app/about(无需认证)。自写 compose 时可直接复用:
healthcheck:
test: ["CMD", "/app/healthcheck.sh"]
interval: 30s
timeout: 10s
retries: 3
八、常见坑与排障(实测/日志证据)
- 默认凭据暴露公网:首次启动即有
changeme@example.com/MyPassword管理员。ALLOW_SIGNUP=false只挡注册、不挡这个内置账号。公网部署必须:改密 + 用反代限制来源 + 考虑关掉API_DOCS(默认 True,/docs暴露全部 API 结构)。 - PUID/PGID 不匹配:数据目录属主与 PUID 不一致时,run.sh 的
chown -R只在 root 启动路径执行;若以非 root 起容器且目录不可写,迁移阶段直接失败。把 PUID/PGID 显式设为数据目录属主是最省事的解法。 - 端口占用:日志报
ERROR [Errno 98] Address already in use (while attempting to bind on address ('::', 9000))即容器内 9000 已被占(例如误在运行中的容器里手动再起mealie进程)。宿主机端口冲突则在 compose 改ports映射,不要动API_PORT。 - 内网 URL 抓取导入失败:贴一个解析到私网地址的链接导入食谱会被 SSRF 防护拦截。实测解法:
HTTP_ALLOW_LIST加入目标网段(本例10.89.56.0/24),重启后POST /api/recipes/create-url成功导入(返回 slugmapo-tofu)。注意 compose 改了环境变量要up -d重建容器才生效——实测旧日志里HTTP_ALLOW_LIST显示为空串,就是"启动早于 compose 编辑"的时序问题,用docker inspect确认当前容器实际注入值可快速定位此类问题。 - PG 未就绪抢跑:不给 postgres 配
pg_isready健康检查、depends_on不带condition: service_healthy,冷启动时 Mealie 会因连不上库而退出重启,拉长就绪时间。 - 模糊搜索"不生效":SQLite 形态无 fuzzy search,属预期行为(官方文档 + 迁移日志
postgres fuzzy search步骤仅在 PG 库出现),不是 bug;需要该特性就换 PG 形态。 - 升级:直接改镜像 tag 后
docker compose up -d,新容器启动时自动跑增量迁移(本例全新库一次跑完 62 步;老库只跑未应用步骤)。升级前先用应用内备份或pg_dump/冷拷贝兜底(操作见 CLI 篇)。
九、参考链接
- 官方文档 · 安装清单:https://docs.mealie.io/documentation/getting-started/installation/ (查询日期 2026-11-02)
- 官方文档 · SQLite 部署:https://docs.mealie.io/documentation/getting-started/installation/sqlite-setup (查询日期 2026-11-02)
- 官方文档 · PostgreSQL 部署:https://docs.mealie.io/documentation/getting-started/installation/postgres-setup (查询日期 2026-11-02)
- 官方文档 · 后端配置:https://docs.mealie.io/documentation/getting-started/installation/backend-config (查询日期 2026-11-02)
- 官方镜像:https://ghcr.io/mealie-recipes/mealie
- 官方仓库:https://github.com/mealie-recipes/mealie
- 本专栏认知篇:《Mealie 介绍与选型指南》;配置篇:《Mealie 3.30.0 配置参数详解》;运维篇:《Mealie 3.30.0 常用 CLI 命令与工具详解》