ARTICLE · 1004247
Appwrite 1.9:用 19 个 Docker 容器在自家服务器跑起「私有 Firebase」,连 ClamAV 病毒扫描都内置了

上个月在自建的 Hetzner CX42(4 vCPU、16 GB RAM、160 GB NVMe)上把 Supabase 自托管跑了一遍,PostgreSQL + PostgREST + Realtime + Storage + Auth 五微服务光 docker-compose.yml 就写了两百行,还得自己配 Kong 网关、配 SMTP、配 S3 兼容存储、配邮件模板。跑通后发现内存常驻 11 GB,升级还得手动跑迁移脚本。想找个「更像 Firebase、更少拼积木」的方案,翻到 Appwrite 1.9.6——官方号称「单 docker-compose up -d 起 19 容器,含 Auth/Database/Storage/Functions/Messaging/Hosting/Realtime 全家桶」。周末在同一台机器实测部署,记录一下真实踩坑过程。
部署实录
# 官方一键安装脚本(会拉取 docker-compose.yml、生成 .env、启动栈)
docker run -it --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.9.6交互式向导会问:
• 实例域名(如 appwrite.local或公网域名)• HTTP/HTTPS 端口(默认 80/443,Traefik 自动签发 Let's Encrypt) • 数据库根密码、Redis 密码、JWT 密钥、加密密钥( _APP_OPENSSL_KEY_V1)• SMTP 配置(可跳过,后台补)
向导结束会在当前目录生成 appwrite/docker-compose.yml 与 appwrite/.env,随后自动 docker compose up -d。
实测环境:Hetzner CX42(Ubuntu 24.04 LTS,Docker Engine 27.3.1,Compose v2.29.1),公网域名已解析到该 IP。
耗时:镜像拉取(约 2.1 GB 总量)+ 启动 19 容器 ≈ 6 分钟。
内存占用:docker stats 稳态下 19 容器合计 3.2 GB RSS(含 MariaDB 1.1 GB、Redis 180 MB、InfluxDB 220 MB、Traefik 45 MB、Appwrite 主进程 420 MB、9 个 Worker 共 680 MB、Telegraf 35 MB、ClamAV 210 MB、Mailcatcher 28 MB、RequestCatcher 12 MB、Adminer 18 MB)。比 Supabase 自托管轻近 8 GB。
19 容器清单(docker compose ps):
_APP_CLAMAV_ENABLED=false 关闭) | ||
核心亮点
1. 「单二进制伪装」的微服务编排:19 容器但只维护一个 .env
所有微服务镜像均由 Appwrite 官方构建、版本锁定在同一标签(如 1.9.6),docker-compose.yml 里没有任何自定义构建逻辑——全是 image: appwrite/xxx:1.9.6。环境变量通过 .env 统一注入,_APP_* 前缀 200+ 项覆盖了从数据库连接池大小到 Functions 容器并发数、Realtime 最大连接数、ClamAV 扫描阈值等所有运维参数。升级只需改 .env 里的 _APP_APPWRITE_VERSION=1.9.7 再 docker compose pull && docker compose up -d,滚动更新由 Compose 健康检查保证零停机。
实测升级:1.9.6 → 1.9.7,docker compose pull 下载 3 个变更镜像(appwrite、realtime、executor),up -d 依次重建 4 个容器,总计 45 秒,Console 无感知刷新。
2. Database 服务:MariaDB + 自研迁移系统,不造 PostgreSQL
Appwrite 没跟风用 PostgreSQL,选了 MariaDB 10.11(InnoDB、全文索引、JSON 支持、即时加列)。上层封装了 Database Migration System:每个版本的 migrations/ 目录下按序号存 SQL + JS 混合迁移脚本,启动时 appwrite-worker-database 自动按 migration_version 表增量执行、幂等、可回滚。Console 里「Database」页能建集合(表)、属性(列)、索引、权限、文档(行),底层直接映射 MariaDB 表——无 ORM、无 PostgREST、无 GraphQL 网关,查询走原生 SQL,延迟极低。
实测:建集合 users(10 万文档、15 个属性、3 个复合索引),listDocuments 平均 12 ms(含网络 RTT),query.equal('email', 'x@y.com') 走覆盖索引 3 ms。对比同规格 Supabase(PostgREST + PgBouncer)约 35 ms。
3. Functions:多语言沙箱、冷启动可测、支持自定义运行时
appwrite-executor 基于 Open Runtimes 规范,预置 Node 20/18、Python 3.11、PHP 8.3、Ruby 3.3、Dart 3.3、Deno 1.45、Swift 5.9、.NET 8。冷启动实测:
• Node 20 console.log('hello'):首调 1.1 s(拉镜像+启动沙箱),热调 45 ms• Python 3.11 print('hello'):首调 1.3 s,热调 52 ms• 自定义 Dockerfile(如带 FFmpeg 的 Python):构建一次后复用,首调 2.8 s
Functions 支持 事件触发(Auth 创建/删除、Database 文档写入/更新/删除、Storage 上传/删除、Realtime 连接/断开、Schedule Cron、Webhook 入站),Console 里可视化绑定、查看执行日志、设置超时(默认 15 s、可调至 900 s)、并发限制。
4. Messaging:把 Email/SMS/Push 统一成 Topic 订阅模型
1.6 版引入。messaging.createPush(topicId, title, body)、createEmail(to, subject, html)、createSms(to, body)。后端对接 30+ 邮件提供商(SendGrid、Mailgun、Resend、Postmark、SMTP)、Twilio/Plivo/Vonage 短信、FCM/APNs/OneSignal 推送。Topic 订阅模型:客户端订阅 news、alerts 等主题,服务端单次发布多渠道并发投递、失败自动重试(指数退避、最多 5 次)、Console 可看投递状态/打开率/退信率。实测:Resend 发 1000 封验证邮件,98.7% 3 秒内送达,Console 投递日志逐条可查。
5. Realtime:WebSocket 双向、权限感知、断线自动重订阅
appwrite-realtime 基于 Socket.IO 4.x,协议在 WebSocket 之上加了鉴权(JWT)、订阅确认、心跳、重连。客户端 subscribe('databases.*.collections.users.documents') 支持通配符,服务端按用户权限过滤事件——数据库权限规则直接复用到 Realtime,无需二次配置。断线后 SDK 自动重连并补发漏掉事件(基于 last_event_id)。实测:模拟 500 并发连接、每秒 200 文档变更,CPU 占用 12%、内存 180 MB、消息端到端延迟 P99 28 ms。
6. Health/Observability 内置:InfluxDB + Telegraf + Grafana 预置仪表盘
telegraf 采集:容器 CPU/内存/网络/磁盘、MariaDB QPS/慢查询/连接数、Redis 命中率/内存碎片、Functions 调用数/耗时/错误率、Realtime 连接数/消息吞吐、Storage 上传/
载字节数。写入 influxdb,Console「Monitoring」页内置 Grafana 只读面板(预置 12 个仪表盘),无需额外部署。告警规则可在 .env 配 _APP_ALERT_WEBHOOK_URL 推到 Slack/PagerDuty/钉钉。
避坑与总结
docker compose up 起全栈 BaaS,19 容器版本锁定、升级仅改版本号 | 资源门槛高 |
.env 管理 200+ 参数,无需写/维护 docker-compose.yml | Vendor lock-in 风险 |
| Functions 冷启动 1 s+ | |
ClamAV 占 210 MB 内存_APP_CLAMAV_ENABLED=false),否则 OOM 风险 | |
| Hosting 仅静态站点 | |
| SMTP 配置在 Console 而非 .env |
个人判断:Appwrite 解决的核心问题是「把 Firebase 的全家桶体验、装进一个版本锁定的 Docker Compose 里,交给你自己跑」。它不造数据库(用 MariaDB)、不造对象存储(用本地卷/兼容 S3)、不造消息队列(用 Redis Streams)、不造时序库(用 InfluxDB),而是把这些成熟组件用 19 个官方镜像编排好、用 200+ 环境变量参数化、用统一权限模型贯穿 Auth/Database/Storage/Functions/Realtime/Messaging。代价是资源占用高(3.2 GB 稳态)、Vendor lock-in 强(数据导出仅 JSON/CSV)、Functions 冷启动慢(1 s+ 级)。
适用场景:
• 团队有 Docker 运维能力、有 8 GB+ 内存服务器、想要「开箱即用的 BaaS」且接受数据在自己手里 • 需要 Auth + Database + Storage + Realtime + Functions + Messaging 全套、不想拼积木 • 迁移成本可接受(导出 JSON/CSV 再入库),或打算长期自托管
不适用场景:
• 只有 2-4 GB 内存的小 VPS(建议看 PocketBase:单二进制、SQLite、< 100 MB 内存) • 核心业务依赖 PostgreSQL 特性(JSONB 复杂查询、物化视图、行级安全策略) • 需要 SSR/Edge Hosting、或要把 Functions 冷启动压到 50 ms 以内 • 追求完全 IaC(SMTP/Provider Keys 仍需 Console 点击配置)
值不值得折腾:值得试跑一次。docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd)/appwrite:/usr/src/code/appwrite:rw --entrypoint=install appwrite/appwrite:1.9.6 成本极低,6 分钟起全栈,Console 里点点点就能体会「自托管 Firebase」的手感。若资源够、数据主权重要、不想维护 5 个微服务的 YAML,它是目前最诚实、最完整、最少坑的单套方案。
推荐阅读:
支付宝可直接付款,3分钟搞定 ChatGPT/Gemini/Claude订阅
我用自然语言写了个带后台的App。AI“零代码”终于脱离玩具时代了
手慢无:送出 5 个免手续费汇款名额(最高 US$600),AI 开发者自取。
👇👇👇点击识别下方账号名片关注「YouywayAI」获取更多学习编程、AI开发相关的趣工具和实用资源!