Mafl 0.15.4 Docker Compose 部署指南

Mafl v0.15.4 Docker Compose 部署全流程实测:config.yml 挂载与生效机制、健康检查与 /api/settings/TCP 状态探测验证链、PORT 与 NITRO_SSL 环境变量及 HTTPS 直连实测,含无配置 500、tags 类型崩溃、热更新需页面在线三段排障实录。

MaflMaflDockerDocker Compose面板2026/11/03

Mafl 0.15.4 Docker Compose 部署指南

目标:在单台 Ubuntu 22.04 服务器上以 Docker Compose 部署 Mafl v0.15.4 首页面板,完成 config.yml 持久化挂载、分组/标签/状态检查配置、健康检查与 /api/settings 验证、HTTPS 直连形态与端口自定义,并沉淀「无配置 500」「配置改动不生效」「tags 类型错误崩溃」三段排障实录。本文全部命令与回显已在 Docker Engine 29.9.2(Compose v5.6.1)环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Docker Engine:29.9.2,Docker Compose 插件 v5.6.1
  • Mafl 版本:v0.15.4(2024-07-13 发布,官方最新 Release)
  • 官方镜像:hywax/mafl:v0.15.4(Docker Hub,另有 GHCR 渠道 ghcr.io/hywax/mafl),镜像内容层约 48.2MB,底座 Alpine Linux 3.20.1 + Node.js v20.15.1
  • 应用监听端口:实例内 3000(Nitro 默认);本教程宿主映射 8132,生产可改 3000 或由反代接管
  • 编排目录:/opt/mafl/(示例路径,含 docker-compose.yml 与配置子目录 mafl/)
  • 独立网络:mafl-net(bridge,网段 10.89.59.0/24,显式子网避免与同机其他编排栈冲突)
  • Compose 项目名:mafl-v0154-stack(显式 name:,防止与其他组件栈互相误删)
  • 演示访问账号:Mafl 无内置认证;如需公网暴露,请在反向代理层配置账号 root / 密码 q1w2e3r4 的 Basic Auth(见第十一章常见问题 6)

二、镜像选型说明

Mafl 官方在 Docker Hub 与 GHCR 双渠道发布同一构建,选型要点集中在仓库地址与标签策略:

渠道/标签含义适用场景
hywax/mafl:v0.15.4精确版本标签(Docker Hub)生产推荐,升级可控、回显可复现
hywax/mafl:latest滚动最新仅测试尝鲜,面板类「latest 即最新 Release」,风险低于数据库类
ghcr.io/hywax/maflGitHub 容器仓库同构建Docker Hub 受限时的备用渠道

实测拉取(2026-11-02):

docker pull hywax/mafl:v0.15.4
10c28d5fbad7: Pull complete
f2f35e6867e8: Pull complete
Digest: sha256:2c89020be334b341da41a6b95830b1b52b1b9f43c9f16d09c0ab4e9dad3ea4ad
Status: Downloaded newer image for hywax/mafl:v0.15.4
docker.io/hywax/mafl:v0.15.4

输出节选(实测首尾)。锁定 digest 便于供应链核对:sha256:2c89020be334b341da41a6b95830b1b52b1b9f43c9f16d09c0ab4e9dad3ea4ad。

docker images hywax/mafl
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hywax/mafl:v0.15.4   2c89020be334        196MB         48.2MB

💡 说明:镜像内置健康检查(node /app/extra/healthcheck.mjs,每 10 秒 GET localhost:3000/api/health,状态码 200 记健康),docker compose ps 可见健康状态,无需另配。

三、前置条件

  1. Docker Engine ≥ 24 与 Compose v2 插件(本文实测 29.9.2 / v5.6.1);
  2. 宿主端口 8132 空闲:
ss -ltn | grep -E ':(8132)\b'

(无输出即空闲)

  1. 编排目录与配置子目录:
mkdir -p /opt/mafl/mafl

⚠️ 网络说明:docker pull 经宿主 Docker 守护进程代理渠道完成(官方源直连当时不可用,现象为连接超时;守护进程已配置代理 192.168.1.62:7897,实测可用)。服务器上若 Docker Hub 直连正常则无需任何额外配置;GHCR 渠道 ghcr.io/hywax/mafl 可作降级备选。

四、部署步骤

4.1 编写 compose 编排文件

cat > /opt/mafl/docker-compose.yml <<'EOF'
name: mafl-v0154-stack

services:
  mafl:
    image: hywax/mafl:v0.15.4
    container_name: mafl-v0154-web
    restart: unless-stopped
    ports:
      - '8132:3000'
    volumes:
      - ./mafl/:/app/data/
    networks:
      - mafl-net

networks:
  mafl-net:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.59.0/24
EOF

逐项说明:

  • name: 显式项目名,多组件同机共存时 docker compose down 只影响本栈;
  • ports: '8132:3000' 宿主 8132 → 实例 3000(应用端口固定 3000,除非注入 PORT 环境变量,见第六章);
  • volumes: ./mafl/:/app/data/ 把配置目录持久化到宿主,config.yml 就放在这里;
  • ipam 显式网段,避免自动分配与既有栈撞段。

4.2 首次启动(空配置,观察真实行为)

先不写 config.yml 直接启动,这是官方文档未明说但必须掌握的行为基线:

cd /opt/mafl && docker compose up -d
 Network mafl-v0154-stack_mafl-net Creating 
 Network mafl-v0154-stack_mafl-net Created 
 Container mafl-v0154-web Creating 
 Container mafl-v0154-web Created 
 Container mafl-v0154-web Starting 
 Container mafl-v0154-web Started
docker compose logs --tail=30
mafl-v0154-web  | Listening on http://[::]:3000
mafl-v0154-web  | Error: Config not found
mafl-v0154-web  |     at loadConfig (file:///app/server/chunks/_/config.mjs:96:13)
mafl-v0154-web  |     at async Object.run (file:///app/server/chunks/tasks/update.mjs:32:20)
mafl-v0154-web  |     at async runTask (file:///app/server/chunks/runtime.mjs:10319:17)
mafl-v0154-web  | Set "main" config
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8132/
HTTP 500

⚠️ 排障实录 ①:config.yml 缺失时进程不会退出、健康检查照常通过(docker compose ps 显示 Up (healthy)),但所有页面请求返回 500。日志里的 Error: Config not found 就是根因——「healthy 但 500」不要往网络方向查,先查配置文件是否挂载到位。

4.3 编写 config.yml 并重启

cat > /opt/mafl/mafl/config.yml <<'EOF'
title: Quzuo Home Page
lang: zh
theme: dark
checkUpdates: false
behaviour:
  target: _self
tags:
  - name: Infra
    color: green
  - name: Demo
    color: blue
layout:
  grid:
    small: 1
    medium: 2
    large: 3
    xlarge: 4
services:
  Infrastructure:
    - title: Mafl Panel
      description: 面板实例自身(状态应为在线)
      link: http://127.0.0.1:3000/
      icon:
        name: mdi:view-dashboard
        wrap: true
        color: '#3dbcf3'
      status:
        enabled: true
      tags:
        - Infra
  Tools:
    - title: Dead Service
      description: 指向未监听端口(状态应为离线)
      link: http://127.0.0.1:3999/
      icon:
        name: mdi:power-plug-off
        wrap: true
      status:
        enabled: true
        interval: 30
      tags:
        - Demo
    - title: Docs Site
      description: 官方文档(无状态检查)
      link: https://mafl.hywax.space/
      icon:
        name: simple-icons:mdbook
        wrap: true
EOF

配置结构要点(逐参数详解见 《Mafl 0.15.4 配置参数详解》篇):

  • 全局层:title 页面标题、lang: zh 中文界面、theme: dark 深色主题、checkUpdates 关闭版本提示、behaviour.target 链接跳转方式、tags 全局标签定义、layout.grid 各断点列数;
  • 服务层:services 用「组名: [卡片列表]」的分组形态;每张卡片 title/link 必填语义位,icon.name 支持 Iconify 图标名,status.enabled 开启 TCP 状态灯,tags 引用全局标签名。
docker compose restart
 Container mafl-v0154-web Restarting 
 Container mafl-v0154-web Started
docker compose logs --since 30s
mafl-v0154-web  | Listening on http://[::]:3000
mafl-v0154-web  | Set "main" config

Set "main" config 即配置加载成功标记,且不再出现 Error: Config not found。

4.4 验证部署

curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8132/
HTTP 200
curl -s http://127.0.0.1:8132/ | grep -oE "<title>[^<]*</title>"
<title>Quzuo Home Page</title>
curl -s http://127.0.0.1:8132/api/health -o /dev/null -w "health HTTP %{http_code}\n"
health HTTP 200
docker compose ps
NAME             IMAGE                COMMAND                  SERVICE   CREATED         STATUS                   PORTS
mafl-v0154-web   hywax/mafl:v0.15.4   "docker-entrypoint.s…"   mafl      4 minutes ago   Up 3 seconds (healthy)   0.0.0.0:8132->3000/tcp, [::]:8132->3000/tcp

浏览器访问 http://<服务器IP>:8132/ 可见中文界面、双分组卡片与状态灯(Mafl 状态灯由服务端 TCP 探测驱动,实测响应见 4.5)。

4.5 状态检查链路实测(服务端 API)

面板的状态灯数据可通过内部 API 独立核对。先从 /api/settings 取服务 UUID,再调 base 服务探测端点:

ID=$(curl -s http://127.0.0.1:8132/api/settings | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['services'][0]['items'][0]['id'])")
curl -s "http://127.0.0.1:8132/api/services/base?id=$ID"
{"ping":{"status":true,"time":0},"data":{}}

在线服务(127.0.0.1:3000)返回 status: true。对离线目标:

ID2=$(curl -s http://127.0.0.1:8132/api/settings | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['services'][1]['items'][0]['id'])")
curl -s "http://127.0.0.1:8132/api/services/base?id=$ID2"
{"ping":{"status":false,"time":null},"data":{}}

未开启 status.enabled 的卡片则响应中根本没有 ping 字段(实测 {"data":{}})——状态灯只反映显式开启检查的服务。

五、数据持久化说明

宿主路径实例路径类型说明
/opt/mafl/mafl/config.yml/app/data/config.yml文件唯一必需配置文件
/opt/mafl/icons//app/public/icons/目录本地图标(可选,卡片 icon.url 按文件名引用)
/opt/mafl/favicons//app/public/favicons/目录站点图标(可选)

Mafl 没有任何数据库:全部状态即 config.yml 一个文件,备份 = 拷贝该文件;重建 = 换一台服务器挂载同文件。实测重建验证:

cd /opt/mafl && docker compose down && docker compose up -d
 Container mafl-v0154-web Stopping 
 Container mafl-v0154-web Stopped 
 Container mafl-v0154-web Removing 
 Container mafl-v0154-web Removed 
 Network mafl-v0154-stack_mafl-net Removing 
 Network mafl-v0154-stack_mafl-net Removed 
 Network mafl-v0154-stack_mafl-net Creating 
 Network mafl-v0154-stack_mafl-net Created 
 Container mafl-v0154-web Creating 
 Container mafl-v0154-web Created 
 Container mafl-v0154-web Starting 
 Container mafl-v0154-web Started
curl -s http://127.0.0.1:8132/ | grep -oE "<title>[^<]*</title>"
<title>Quzuo Home Page</title>

六、环境变量表

Mafl 本体不读业务环境变量(一切走 config.yml),可注入的是 Nitro 运行时层参数(实测有效项):

变量默认实测行为
PORT3000设 3005 后日志变 Listening on http://[::]:3005,端口映射需同步改
HOST::监听地址
NITRO_SSL_CERT无传入证书 PEM 内容(非路径)即启用 HTTPS
NITRO_SSL_KEY无传入私钥 PEM 内容,与上项配对
NITRO_UNIX_SOCKET无改 Unix socket 监听(对接反代)
NITRO_SHUTDOWN_TIMEOUT—优雅停机超时

PORT 实测(独立验证实例,宿主映射 8134):

docker run -d --name mafl-v0154-envtest --network mafl-slot60-probe -e PORT=3005 -p 8134:3005 -v /opt/mafl/mafl:/app/data hywax/mafl:v0.15.4
docker logs mafl-v0154-envtest
Listening on http://[::]:3005
Set "main" config
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8134/
HTTP 200

HTTPS 直连实测(不挂反代、证书以内容注入):

openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=mafl-test"
docker run -d --name mafl-v0154-tlstest -e NITRO_SSL_CERT="$(cat server.crt)" -e NITRO_SSL_KEY="$(cat server.key)" -p 8134:3000 -v /opt/mafl/mafl:/app/data hywax/mafl:v0.15.4
docker logs mafl-v0154-tlstest
Listening on https://[::]:3000
Set "main" config
curl -sk -o /dev/null -w "HTTPS %{http_code}\n" https://127.0.0.1:8134/
HTTPS 200

⚠️ 注意:证书以环境变量内容注入会进入 docker inspect 可见范围,生产建议优先走 Nginx/Caddy 反代终结 TLS;NITRO_SSL_* 适合内网快速验证。

七、配置参数说明(速览)

config.yml 全局参数与默认值(默认值取自实例内置出厂配置,经 /api/settings 合并结果实测核对):

参数默认值一句话说明
titleMafl Home Page页面标题
langen界面语言,支持 zh
themesystemsystem/light/dark/deep/sepia/bluer
checkUpdatestrue新版本横幅提示(不自动更新)
behaviour.target_blank卡片跳转方式,可被单卡片 target 覆盖
layout.gridsmall 2 / medium 2 / large 3 / xlarge 4各断点网格列数(1-12)
tags[]全局标签(name+color)
services[](缺失则首页报错)卡片列表或分组映射

逐参数语义、服务卡片字段、type/options/secrets 与服务类型的完整实测见 《Mafl 0.15.4 配置参数详解》篇。

八、配置文件挂载

官方文档明确「必须显式提供 config.yml,其余路径可默认」。挂载形态二选一:

# 形态 A(本文采用):目录挂载,便于同时放图标目录与备份
volumes:
  - ./mafl/:/app/data/
# 形态 B(官方 docker run 示例采用):单文件挂载
volumes:
  - ./config.yml:/app/data/config.yml

⚠️ 排障实录 ②:改了 config.yml 页面不更新。Mafl 的配置热更新由 WebSocket 通道驱动——只有当浏览器页面处于打开状态(/api/websocket 有活跃 peer)时,服务端才监听配置文件变化并自动重载。实测无浏览器在线时修改 title 后 10 秒内页面不变、日志无 Set "main" config;两种生效路径:① 保持页面打开,保存文件即秒级生效(页面标题实测变为新值);② 无人在线时执行 docker compose restart。完整链路验证见 《Mafl 0.15.4 日常运维手册》篇第二章。

九、等价 docker run

compose 编排等价的一次性运行(官方 README 形态 + 本文端口):

docker run -d --name mafl-v0154-web -p 8132:3000 -v /opt/mafl/mafl:/app/data --restart unless-stopped hywax/mafl:v0.15.4

官方 README 给出的最小形态(单文件挂载、默认 3000 端口):

docker run --name mafl -p 3000:3000 -v ./config.yml:/app/data/config.yml hywax/mafl

十、常用运维命令

# 查看运行与健康状态
docker compose ps

# 跟踪日志(配置加载标记为 Set "main" config)
docker compose logs -f

# 重载配置(无浏览器在线时的必选路径)
docker compose restart

# 升级到新版本:改 compose 中 image 标签后
docker compose pull && docker compose up -d

# 回滚:把 image 标签改回 v0.15.4 再执行上两条命令

升级实测(v0.15.3→v0.15.4 同理,标签替换即可):

docker pull hywax/mafl:v0.15.4
docker compose up -d
 Container mafl-v0154-web Recreate 
 Container mafl-v0154-web Recreated 
 Container mafl-v0154-web Starting 
 Container mafl-v0154-web Started

十一、常见问题(FAQ)

Q1: 页面 500,日志 Error: Config not found? A: config.yml 未挂载或路径错。docker compose exec 进实例 ls /app/data 核对(实测空目录时即此现象,见 4.2)。

Q2: 启动日志 TypeError: tags.reduce is not a function,页面 500? A: tags 写成了字符串而非数组。实测 tags: work 触发该崩溃(tags 解析发生在 schema 校验之前,报错先于任何字段校验)。正确形态:

tags:
  - name: Infra
    color: green

Q3: 卡片拼错字段名(如 titel)为什么不报错? A: Mafl 的配置 schema 对未知键静默透传(实测 titel: typo 原样进入 /api/settings 响应,页面渲染为无标题空卡片)。配置自检唯一可靠手段是回读 /api/settings 比对(见 《Mafl 0.15.4 配置参数详解》篇参数查看章节)。

Q4: HTTPS 服务卡片状态灯总是「离线」? A: 状态检查是 TCP 探测且端口缺省取 80:https://example.com/ 这类不带显式端口的链接探测的是 80 端口。给 link 写明端口(如 https://example.com:8443/)即可修正(探测逻辑实测见配置篇)。

Q5: 能否多用户/登录访问? A: 不能,Mafl 无内置认证。公网部署务必置于反代之后并启用认证,例如 Nginx 层:auth_basic "Mafl"; auth_basic_user_file /etc/nginx/mafl-passwd;,用账号 root / 密码 q1w2e3r4 生成口令文件:printf 'root:%s\n' "$(openssl passwd -apr1 q1w2e3r4)" > /etc/nginx/mafl-passwd。

Q6: 更新横幅出现是否意味着已自动升级? A: 否。checkUpdates: true 只提示新版本,升级需手动换标签(第十章);官方建议自动化场景使用 watchtower。

十二、参考链接

Mafl 0.15.4 Docker Compose 部署指南 - Quzuo