Fusio 7.2.1 Docker Compose 部署指南

在一台 Linux 服务器上用 Docker Compose 从零部署 Fusio 7.2.1 自托管 API 管理平台(fusio 应用 + MySQL 9 数据库),完成启动、自动初始化、健康验证、数据持久化与日常运维,全程命令与回显均已在真实环境实测通过。

FusioFusioAPIPHP2026/10/24

Fusio 7.2.1 Docker Compose 部署指南

目标:在一台 Linux 服务器上用 Docker Compose 从零部署 Fusio 7.2.1 自托管 API 管理平台(fusio 应用 + MySQL 9 数据库),完成启动、自动初始化、健康验证、数据持久化与日常运维,全程命令与回显均已在真实环境实测通过。

一、环境信息

本文所有命令与回显在以下环境实测通过(写作日期 2026-10-24,版本为当时官方最新稳定版):

  • 操作系统:Ubuntu 22.04(x86_64,内核 5.15+ 均可)
  • Docker Engine:29.x(含 docker compose v2 插件)
  • Fusio 版本:7.2.1(镜像 fusio/fusio:7.2.1)
  • 数据库:MySQL 9(镜像 mysql:9,实测版本 9.7.4)
  • 部署目录:/opt/fusio/(含 docker-compose.yml 与数据目录 db/)
  • 服务端口:宿主机 8148 → 容器 80(8148 为实测所用端口,可按需更换为任意空闲端口)
  • 演示账号:后台管理员 admin / q1w2e3r4;MySQL root 密码 q1w2e3r4;MySQL 业务账号 fusio / q1w2e3r4(均为演示口令,生产环境必须更换)
  • 平台版本溯源:v7.2.1 为 GitHub releases.atom 实查最新稳定版(2026-10-24 查询,发布说明含 OpenAPI 3.1.2 升级与两项 CVE 镜像修复)

二、镜像选型说明

Fusio 官方在 Docker Hub 发布 fusio/fusio 镜像,选型前需先弄清标签体系(以下标签信息于 2026-10-24 实查 Docker Hub 标签页):

镜像标签用途说明
fusio/fusio:7.2.1生产推荐精确版本标签,升级可控,本文采用
fusio/fusio:7.2跟随 7.2.x 补丁小版本浮动标签
fusio/fusio:latest最新稳定版便于尝鲜,生产不建议(升级不可控)
fusio/fusio:latest-mssql需连接 MSSQL内置 mssql PHP 扩展的变体
fusio/fusio:latest-oracle需连接 Oracle内置 oracle PHP 扩展的变体
fusio/fusio:main主分支开发版不稳定,禁用于生产

💡 技术拓展:数据库镜像的选择不止 mysql:9 一种。Fusio 支持多种后端库(连接串以 pdo- 前缀区分),常见组合对比——

组合连接串前缀适用场景
MySQL 8/9(mysql:9)pdo-mysql://官方 Compose 默认,本文实测组合
PostgreSQL(postgres:16)pdo-pgsql://已有 PG 运维体系时
MariaDB(mariadb:11)pdo-mysql://(协议兼容)替代 MySQL 的轻量选择
SQLite文件型连接极小规模/试用

本文实际采用官方 Compose 的 MySQL 9 组合:与官方部署文档一致、坑最少;MSSQL/Oracle 属"把外部库接入 Fusio 当数据源",与"Fusio 自身元数据库"是两回事,后者官方仅保证 MySQL/PG 等主流库。

关键差异:镜像标签选择的核心原则是"生产用精确版本号 + 升级靠改 tag",数据库镜像同理固定大版本。

三、前置条件

  1. 已安装 Docker Engine 24+ 与 docker compose v2 插件(docker compose version 能正常输出版本):
docker compose version

实测回显(本文环境):

Docker Compose version v2.39.2
  1. 服务器可访问外网(拉取镜像);内网环境请提前离线导入 fusio/fusio:7.2.1 与 mysql:9 两份镜像。
  2. 端口规划:确认宿主机 8148 端口未被占用(被占用则换其他空闲端口,并同步修改后文 Compose 文件):
ss -ltn | grep 8148 || echo "8148 端口空闲"

实测回显:

8148 端口空闲
  1. 磁盘余量:镜像合计约 1.6GB,另需为数据库数据目录预留空间(建议 5GB 起步)。

四、部署步骤

4.1 创建部署目录与 Compose 文件

mkdir -p /opt/fusio/db
cat > /opt/fusio/docker-compose.yml <<'EOF'
name: fusio-7.2.1-stack

services:
  fusio:
    image: fusio/fusio:7.2.1
    restart: always
    depends_on:
      - mysql-fusio
    environment:
      FUSIO_PROJECT_KEY: "42eec18ffdbffc9fda6110dcc705d6ce"
      FUSIO_ENV: "prod"
      FUSIO_DEBUG: "false"
      FUSIO_CONNECTION: "pdo-mysql://fusio:q1w2e3r4@mysql-fusio/fusio"
      FUSIO_BACKEND_USER: "admin"
      FUSIO_BACKEND_EMAIL: "admin@example.com"
      FUSIO_BACKEND_PW: "q1w2e3r4"
      FUSIO_URL: "http://192.168.1.62:8148"
    ports:
      - "8148:80"

  mysql-fusio:
    image: mysql:9
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "q1w2e3r4"
      MYSQL_USER: "fusio"
      MYSQL_PASSWORD: "q1w2e3r4"
      MYSQL_DATABASE: "fusio"
    volumes:
      - ./db:/var/lib/mysql

networks:
  default:
    name: fusio-721-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.73.0/24
EOF

逐项说明(关键项):

  • name: fusio-7.2.1-stack:显式指定 Compose 项目名,保证多套环境隔离且资源命名可读。
  • FUSIO_PROJECT_KEY:项目密钥,用于加密库内保存的连接凭据。务必在首次安装前改成自己的随机值(一旦安装后再改,历史加密数据将不可读)。
  • FUSIO_CONNECTION:Fusio 自身元数据库的连接串,格式 pdo-mysql://用户:密码@主机/库名;主机名 mysql-fusio 即 Compose 内数据库服务名(Compose 内置 DNS 解析)。
  • FUSIO_BACKEND_USER/EMAIL/PW:首次启动时自动创建的后台管理员账号(本文演示 admin/q1w2e3r4,生产必须换强口令)。
  • FUSIO_URL:对外访问地址,用于生成的规范与链接;改成 http://<服务器IP>:8148 或域名。
  • FUSIO_ENV=prod + FUSIO_DEBUG=false:生产形态,关闭调试输出并启用多级缓存。
  • MYSQL_ROOT_PASSWORD:MySQL root 口令;MYSQL_USER/MYSQL_PASSWORD/MYSQL_DATABASE 由镜像自动建出 fusio 库与同名账号(FUSIO_CONNECTION 使用的就是它)。
  • networks 段把内网固定在 10.89.73.0/24:多套 Compose 并存的服务器上显式固定网段可避免网段耗尽冲突;单套环境也可整段删去,由 Docker 自动分配。
  • restart: always:开机自启与故障自拉起。

4.2 启动并观察自动初始化

cd /opt/fusio
docker compose up -d

实测回显:

[+] Running 3/3
 ✔ Network fusio-721-net      Created
 ✔ Container fusio-721-stack-mysql-fusio-1  Started
 ✔ Container fusio-721-stack-fusio-1        Started

首次启动的 fusio 容器会执行"等待数据库 → 数据库迁移 → 创建管理员 → 部署官方应用"的完整初始化(官方镜像入口脚本固定流程)。观察初始化日志:

docker compose logs fusio | grep -vE "oci8|pdo_oci|PHP Warning"

实测回显(节选,完整日志较长):

[notice] Migrating up to Fusio\Impl\Migrations\Version20261008103540
[notice] finished in 8517.9ms, used 44M memory, 22 migrations executed, 102 sql queries

 [OK] Successfully migrated to version:
      Fusio\Impl\Migrations\Version20261008103540


Check failed
Created user admin successful

Replaced env fusio/account


Replaced env fusio/developer


Replaced env fusio/fusio


Replaced env fusio/redoc


Login successful


Deploy successful!

💡 说明:

  • "Check failed" 属正常现象——入口脚本先用 system:check user 探测是否已初始化,未初始化(检查失败)才会创建管理员,紧接着的 "Created user admin successful" 即为结果。
  • "Replaced env" 四行对应官方四个 Web 应用(后台 fusio、开发者门户 developer、账户中心 account、文档 redoc)完成环境变量替换与部署。
  • 日志中的 oci8/pdo_oci PHP Warning 为默认镜像未内置 Oracle 扩展的提示,使用 MySQL 后端可完全忽略(如需 Oracle 再改用 latest-oracle 标签)。

初始化完成后(首次约 1~2 分钟),Apache 以前台进程接管输出,日志末尾出现:

[mpm_prefork:notice] [pid 1:tid 1] AH00163: Apache/2.4.69 (Debian) PHP/8.4.27 configured -- resuming normal operations

4.3 验证部署结果

① 容器状态验证:

docker compose ps

实测回显:

NAME                            IMAGE               COMMAND                   SERVICE       CREATED          STATUS          PORTS
fusio-721-stack-fusio-1         fusio/fusio:7.2.1   "/docker-entrypoint.…"    fusio         15 minutes ago   Up 15 minutes   0.0.0.0:8148->80/tcp, [::]:8148->80/tcp
fusio-721-stack-mysql-fusio-1   mysql:9             "docker-entrypoint.s…"    mysql-fusio   15 minutes ago   Up 15 minutes   3306/tcp, 33060/tcp

② 健康检查端点验证:

curl -s http://127.0.0.1:8148/system/health

实测回显:

{
    "kind": "https://typehub.cloud/s/fusio/sdk/7.0.14/System_HealthCheck",
    "healthy": true,
    "checks": {
        "System": {
            "healthy": true
        }
    }
}

③ 平台能力面验证(根路径返回 System_About 元数据):

curl -s http://127.0.0.1:8148/

实测回显(节选):

{
    "kind": "https://typehub.cloud/s/fusio/sdk/7.0.14/System_About",
    "apiVersion": "v8.9.3",
    "title": "Fusio",
    "description": "Self-Hosted API Management for Builders.",
    "paymentCurrency": "EUR",
    "categories": [
        "authorization",
        "backend",
        "consumer",
        "default",
        "system"
    ],
    "links": [
        { "rel": "apps",       "href": "http://192.168.1.62:8148/apps" },
        { "rel": "openapi",    "href": "http://192.168.1.62:8148/system/generator/spec-openapi" },
        { "rel": "health",     "href": "http://192.168.1.62:8148/system/health" },
        { "rel": "oauth2",     "href": "http://192.168.1.62:8148/authorization/token" },
        ...
    ]
}

💡 说明:apiVersion: v8.9.3 是后端 API 的规范版本号,与产品版本 7.2.1 不同号,属正常现象。

④ 管理后台验证:浏览器访问 http://<服务器IP>:8148/apps/fusio/,用 admin / q1w2e3r4 登录,能进入仪表盘即部署完成。应用门户列表在 /apps/ 路径(实测 HTTP 200)。

五、数据持久化说明

  • 数据库数据:通过 bind mount ./db:/var/lib/mysql 持久化到宿主机 /opt/fusio/db/,实测部署后该目录即生成 MySQL 数据文件。执行 docker compose down 不丢数据;只有 docker compose down 后手动清空 db/ 目录才会回到未初始化状态(本文排障时即以此方式重置过一次全新安装)。
  • 应用侧状态:Fusio 的路由、操作、用户、日志等全部业务状态都存于数据库,无本地文件状态;应用目录内的 cache/、log/ 为可再生缓存与日志,不需要持久化。
  • 验证持久化:
ls /opt/fusio/db/ | head -8

实测回显:

 #innodb_redo
 #innodb_temp
 auto.cnf
 binlog.000001
 binlog.000002
 binlog.index
 ca-key.pem
 ca.pem

⚠️ 注意:升级或迁移服务器时,只需备份/搬走 db/ 目录(或用 mysqldump 逻辑备份,见"常用运维命令")即可保全全部数据。

六、环境变量表

Fusio 官方镜像通过 FUSIO_* 环境变量完成配置注入(下表为官方 Compose 与镜像入口脚本实际消费的变量,2026-10-24 于官方仓库核实并实测):

变量示例值(本文实测)说明
FUSIO_PROJECT_KEY32 位随机串项目密钥,加密库内连接凭据;仅首次安装前可改
FUSIO_ENVprod运行环境(prod/dev),影响缓存与错误显示
FUSIO_DEBUGfalse调试开关,生产必须 false
FUSIO_CONNECTIONpdo-mysql://fusio:q1w2e3r4@mysql-fusio/fusio元数据库连接串(支持 pdo-pgsql:// 等)
FUSIO_BACKEND_USERadmin自动创建的后台管理员用户名
FUSIO_BACKEND_EMAILadmin@example.com管理员邮箱
FUSIO_BACKEND_PWq1w2e3r4管理员初始密码(生产必须更换)
FUSIO_URLhttp://192.168.1.62:8148平台对外地址(进规范生成与链接)
FUSIO_APPS_URL空/http://x/apps应用门户对外地址(默认跟随主 URL)
FUSIO_MAILERnative://default邮件发送 DSN(可换 smtp://)
FUSIO_MESSENGERdoctrine://default异步消息队列传输(默认走数据库表)
FUSIO_MAIL_SENDERinfo@example.com系统邮件的发件人地址
FUSIO_TRUSTED_IP_HEADER空/X-Forwarded-For反代后取真实客户端 IP 的请求头
FUSIO_TENANT_ID空多租户隔离标识(留空为单租户)
FUSIO_WORKER_JAVA / _JAVASCRIPT / _PHP / _PYTHON空/worker-php:9092对应语言 Worker 的地址,配置后入口脚本自动注册该 Worker 连接
MYSQL_ROOT_PASSWORDq1w2e3r4MySQL root 口令(数据库镜像变量)
MYSQL_USER / MYSQL_PASSWORD / MYSQL_DATABASEfusio / q1w2e3r4 / fusio自动创建的业务账号与库(数据库镜像变量)

💡 说明:全部变量都有内置默认值(如 FUSIO_MAILER 默认 native://default、FUSIO_MESSENGER 默认 doctrine://default),最小配置只需 FUSIO_CONNECTION + 管理员三件套 + FUSIO_URL。变量到内部配置键的完整映射与高级配置(configuration.php)见本专栏 C1 配置篇。

七、配置参数说明

7.1 生产必改项清单

  1. FUSIO_PROJECT_KEY:改成 openssl rand -hex 16 生成的随机值(官方 README 明确警告必须更换默认口令类配置)。
  2. FUSIO_BACKEND_PW 与 MYSQL_ROOT_PASSWORD/MYSQL_PASSWORD:全部换成强口令。
  3. FUSIO_URL:改为对外真实地址(域名 + HTTPS),否则生成的 OpenAPI/TypeAPI 规范里的链接指向错误主机。

7.2 前置反向代理(可选)

Fusio 镜像内置 Apache 监听 80,生产建议前置 Nginx/Caddy 做 TLS 终结,并设置 FUSIO_TRUSTED_IP_HEADER: "X-Forwarded-For" 让限流/防火墙看到真实客户端 IP。此时只需把 Compose 端口映射改为只绑回环(如 127.0.0.1:8148:80),由反代转发。

7.3 Worker 扩展(可选)

需要用 Java/JavaScript/Python 编写自定义 API 逻辑时,在 Compose 中追加对应 worker 服务并在 fusio 服务环境变量中指向它,例如:

  worker-php:
    image: fusio/worker-php:2.1
    restart: always
    volumes:
      - ./worker/php:/var/www/html/worker/actions

同时在 fusio 服务 environment 中加 FUSIO_WORKER_PHP: "worker-php:9092"。重启后入口脚本会自动把 Worker 注册为平台连接(实测入口脚本逻辑:以 Fusio.Adapter.Worker.Connection.Worker 类型自动创建连接)。此段结构转录自官方 apioo/fusio-docker 仓库 Compose 注释原文。

八、配置文件挂载

Fusio 的运行时高级配置位于镜像内 /var/www/html/fusio/configuration.php(返回一个 PHP 配置数组,环境变量只是它的注入来源)。需要覆盖默认值时用 bind mount 覆盖:

  fusio:
    volumes:
      - ./configuration.php:/var/www/html/fusio/configuration.php:ro
  • 先导出镜像内默认文件作底稿再修改:docker compose exec fusio cat /var/www/html/fusio/configuration.php > ./configuration.php
  • 常用的本地覆盖项:fusio_firewall_maxretry(IP 封禁阈值,默认 32)、fusio_expire_token(访问令牌有效期,默认 P2D)、fusio_registration(是否开放自助注册,默认 true)、fusio_mcp(是否启用 HTTP 端点 /mcp,默认 false)。
  • 参数逐项含义、取值范围与生产模板见本专栏 C1 配置篇。

⚠️ 注意:不要把整个 /var/www/html/fusio 目录挂载出来——该目录是应用本体(vendor 等都在其中),空目录覆盖会导致 Could not open input file: bin/fusio、Apache DocumentRoot does not exist 等错误(本文实测排障中复现过该现象)。需要持久化/覆盖的只有 configuration.php、provider.php 等单个文件。

九、等价 docker run

不使用 Compose 时,两条 docker run 可等价启动(先自建网络,与本文实测 Compose 部署等价):

# 1. 创建内网
docker network create --subnet 10.89.73.0/24 fusio-721-net

# 2. 启动 MySQL
docker run -d --name fusio-mysql \
  --network fusio-721-net \
  -e MYSQL_ROOT_PASSWORD=q1w2e3r4 \
  -e MYSQL_USER=fusio \
  -e MYSQL_PASSWORD=q1w2e3r4 \
  -e MYSQL_DATABASE=fusio \
  -v /opt/fusio/db:/var/lib/mysql \
  mysql:9

# 3. 启动 Fusio(等 MySQL 就绪后再启动)
docker run -d --name fusio-app \
  --network fusio-721-net \
  -p 8148:80 \
  --restart always \
  -e FUSIO_PROJECT_KEY=42eec18ffdbffc9fda6110dcc705d6ce \
  -e FUSIO_ENV=prod \
  -e FUSIO_DEBUG=false \
  -e FUSIO_CONNECTION="pdo-mysql://fusio:q1w2e3r4@fusio-mysql/fusio" \
  -e FUSIO_BACKEND_USER=admin \
  -e FUSIO_BACKEND_EMAIL=admin@example.com \
  -e FUSIO_BACKEND_PW=q1w2e3r4 \
  -e FUSIO_URL=http://192.168.1.62:8148 \
  fusio/fusio:7.2.1

说明:--network 使两个实例同网段并通过实例名互通(FUSIO_CONNECTION 中的主机名必须是 MySQL 实例名);其余变量与 Compose 完全一致。生产仍推荐 Compose,编排关系一目了然且升级回滚简单。

十、常用运维命令

以下命令均在 /opt/fusio 目录下实测通过:

① 状态与日志:

docker compose ps          # 实例状态(回显见 4.3①)
docker compose logs -f fusio   # 跟踪 Fusio 日志
docker compose logs fusio 2>&1 | grep -iE "error|migration"   # 过滤错误与迁移记录

② 重启与停止:

docker compose restart fusio    # 重启应用实例
docker compose down             # 停止并移除实例/网络(数据目录 ./db 保留)
docker compose up -d            # 再次启动

③ 逻辑备份与恢复(实测 dump 输出 1687 行,头两行如下):

docker compose exec mysql-fusio mysqldump -uroot -pq1w2e3r4 --databases fusio > /opt/fusio/fusio-$(date +%F).sql

实测回显(文件头部):

-- MySQL dump 10.13  Distrib 9.7.4, for Linux (x86_64)
--
-- Host: localhost    Database: fusio
-- ------------------------------------------------------
-- Server version       9.7.4

恢复:

docker compose exec -T mysql-fusio mysql -uroot -pq1w2e3r4 fusio < /opt/fusio/fusio-2026-10-24.sql

④ 升级版本(入口脚本在每次启动时自动检测并执行未应用的迁移,跨小版本升级只需换镜像标签):

sed -i 's|fusio/fusio:7.2.1|fusio/fusio:7.2.2|' docker-compose.yml
docker compose pull
docker compose up -d
docker compose logs fusio 2>&1 | grep -E "Migrating|migrated"   # 观察升级迁移

⚠️ 注意:升级前务必先做 ③ 的逻辑备份;跨大版本(如 6.x→7.x)请先阅读官方仓库 UPGRADE.md 再操作。

⑤ 回滚:改回旧版本标签后 docker compose up -d;数据库结构回滚无自动机制,恢复升级前的备份文件即可。

十一、常见问题(FAQ)

Q1:日志大量 Unable to load dynamic library 'oci8' / pdo_oci 报错? 不是故障。默认镜像不含 Oracle 扩展,PHP 启动时的加载警告,MySQL/PostgreSQL 后端不受任何影响;确需 Oracle 数据源时换用 fusio/fusio:latest-oracle 标签。

Q2:首次启动卡住或访问 502/连接拒绝? 多数是 MySQL 尚未就绪。Fusio 入口脚本会先等待外部服务(system:wait_for),首次初始化(迁移 22 个版本、102 条 SQL,实测约 8.5 秒 + 应用部署)需 1~2 分钟,稍候即可;持续失败时看两侧日志:docker compose logs fusio 与 docker compose logs mysql-fusio。

Q3:Could not open input file: bin/fusio 且 DocumentRoot ... does not exist? 应用目录被覆盖所致(例如把空目录挂载到了 /var/www/html/fusio)。去掉该挂载、清空数据目录重新 up -d 即可,详见第八节的 ⚠️。

Q4:忘记后台管理员密码? 在应用实例内用 CLI 重置为演示口令(生产换强口令):

docker compose exec fusio php /var/www/html/fusio/bin/fusio system:user_add \
  --role 1 --username admin2 --email admin2@example.com --password '新强口令'

实测回显:

Created user admin2 successful

💡 说明:CLI 的更多用法(含直接生成访问令牌、从数据库一键生成 REST API 的 grid:setup)见本专栏 D1 命令篇。

Q5:健康检查 healthy 为 false? /system/health 会同时检查各数据连接(实测含 System 与自建连接),false 时先看响应 JSON 中哪个子项不健康,再核对该连接的连通性(如数据库口令已改但 FUSIO_CONNECTION 未同步)。

Q6:需要 PostgreSQL 作为元数据库? 把 mysql-fusio 服务替换为 postgres:16,FUSIO_CONNECTION 改为 pdo-pgsql://fusio:q1w2e3r4@postgres-fusio/fusio,数据目录挂载点改为 /var/lib/postgresql/data;其余流程与本文一致。

十二、参考链接