Appwrite Docker Compose 部署指南
基于官方镜像内置安装器生成配置并以 Docker Compose 实测部署 Appwrite 2.5.0 全栈(17 服务/11 镜像):显式子网 10.89.30.0/24 规划、宿主端口 8102 映射、启动与健康验证、根账号/组织/项目/API Key 初始化、资源占用基线,以及地址池冲突、网络重建等 8 条实测排障 FAQ。
Appwrite Docker Compose 部署指南
⚠️ 资源前置要求:Appwrite 2.5.0 完整部署栈包含 17 个服务(API 核心、控制台、实时、worker、定时任务、Traefik 网关、PostgreSQL、Redis、ClickHouse、MQTT、地理服务、浏览器服务、编排器、运行时执行器),需拉取 11 个镜像(合计约 6.5GB 磁盘)。官方最低要求 2 核 CPU / 4GB 内存;本文实测环境 32GB 内存,全栈空载稳态内存占用约 2.4GB。4GB 内存机器可启动但余量极小,生产环境建议 8GB 起步。若内存不足,ClickHouse 与浏览器服务将启动失败或反复重启。
一、环境信息
| 项目 | 内容 |
|---|---|
| 实测日期 | 2026-10-18 |
| 实测版本 | Appwrite 2.5.0(/v1/health/version 实测返回 {"version":"2.5.0"}) |
| 操作系统 | Linux(内核 6.x,x86_64) |
| Docker / Compose | Docker 27.x,Compose v2(docker compose 子命令形式) |
| 宿主出口 | 通过代理 http://192.168.1.62:7897 访问外网(Docker 已配置代理,本文 docker pull 均实测成功) |
| 部署方式 | 官方镜像内置安装器生成 docker-compose.yml + .env,宿主 docker compose up -d 启动 |
| 显式子网 | gateway 10.89.30.0/24、appwrite 10.89.31.0/24、runtimes 10.89.32.0/24、browser 10.89.34.0/24(槽位 30,已避开 192.168.0.0/16 与 100.64.0.0/16) |
| 宿主端口 | 8102 → 容器 80(HTTP),8143 → 443(HTTPS),另有 MQTT 8883、MQTT-WSS 8084 |
| 管理账号 | admin@example.com / q1w2e3r4 |
部署前先确认端口未被占用与路由正常:
ss -ltn | grep -E ':(8102|8143|8883|8084)\b' || echo "ALL FREE"
实测回显:
ALL FREE
ip route get 192.168.1.62
实测回显:
192.168.1.62 via 192.168.146.2 dev ens33 src 192.168.146.128 uid 0
cache
二、部署架构与端口规划
官方安装器(镜像内置的 install 入口)按交互答案生成一套 Compose 配置。2.5.0 的栈组成如下:
| 服务(compose service 名) | 职责 | 实测容器名 |
|---|---|---|
| traefik | 边缘网关,承接 80/443/8883/8084 端口 | appwrite-traefik |
| appwrite | API 核心 | appwrite |
| appwrite-console | Web 管理控制台 | appwrite-console |
| appwrite-realtime | 实时推送 | appwrite-realtime |
| appwrite-worker | 异步任务 worker | appwrite-worker |
| appwrite-task-maintenance / interval / scheduler | 三类定时任务 | appwrite-task-* |
| postgresql | 主数据库(可换 mariadb/mongodb) | appwrite-postgresql |
| redis | 缓存/队列/发布订阅 | appwrite-redis |
| clickhouse | 用量统计与执行日志分析 | appwrite-clickhouse-1 |
| appwrite-mqtt | Realtime MQTT 通道 | appwrite-mqtt |
| appwrite-geo | IP 地理查询 | appwrite-geo |
| appwrite-browser | 浏览器渲染 | appwrite-browser |
| appwrite-autogravity | 镜像加速/预热 | appwrite-autogravity |
| orchestrator | 构建编排 | orchestrator |
| openruntimes-executor | 函数运行时执行器 | exc1 |
端口规划:8102 → 80(API/控制台 HTTP)、8143 → 443(HTTPS)、8883(MQTT)、8084(MQTT over WSS)。后两个端口若不使用 Realtime 可保持默认,仅要求 8102 宿主映射。
三、生成部署配置文件
3.1 拉取官方镜像
官方镜像内含安装器(install 入口),先拉取镜像:
docker pull appwrite/appwrite:2.5.0
实测回显(首次拉取为逐层进度,此处为镜像已存在时的二次执行输出):
2.5.0: Pulling from appwrite/appwrite
Digest: sha256:00bf6b9a0be885e10388dba6dd934a873518efce62b3b5ed6d535026747365c4
Status: Image is up to date for appwrite/appwrite:2.5.0
docker.io/appwrite/appwrite:2.5.0
3.2 用官方安装器生成配置
创建部署目录,把镜像内安装器挂载到该目录运行。参数均为 --key=value 形式(安装器 CLI 只认 = 写法,空格分隔的 --http-port 8102 会报解析错误):
mkdir -p /opt/appwrite/appwrite
docker run -i --rm \
--volume /opt/appwrite/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" appwrite/appwrite:2.5.0 \
--http-port=8102 --https-port=8143 \
--database=postgresql --topology=combined \
--interactive=N --no-start
实测回显(全新空目录、未挂载 docker.sock,完整输出如下):
Warning: Undefined array key 1 in /usr/src/code/packages/cli/src/CLI.php on line 229
Starting Appwrite installation...
Running "docker compose up -d --remove-orphans --renew-anon-volumes"
task.install · 448.9ms · 192890ad
level error
RuntimeException: Failed to start containers
at /usr/src/code/src/Appwrite/Platform/Tasks/Install.php:1397
at /usr/src/code/src/Appwrite/Platform/Tasks/Install.php:767
at /usr/src/code/src/Appwrite/Platform/Tasks/Install.php:332
at /usr/src/code/packages/cli/src/CLI.php:314
... 3 more
────────────────────────────────────────────────────────────
说明:
Warning: Undefined array key 1来自裸旗标--no-start——安装器 CLI 用explode('=')解析参数,不识别无值旗标,可忽略。- 结尾的
RuntimeException: Failed to start containers是预期现象:安装容器没有挂载 docker.sock,无法替你启动服务,但配置文件已经生成完毕。启动放到宿主上做(见第五节),路径一致性更好。 - 若把 docker.sock 挂进安装容器(
--volume /var/run/docker.sock:/var/run/docker.sock),安装器会直接代你启动,但此时 compose 文件路径在容器内/usr/src/code/appwrite/,宿主 daemon 找不到该路径,会报路径错误。因此推荐「容器内生成配置、宿主上启动」的流程。
3.3 核对生成结果
ls -la /opt/appwrite/appwrite/
实测回显:
total 2932
drwxr-xr-x 2 root root 4096 10月 18 20:32 .
drwxrwxrwt 184 root root 2945024 10月 18 20:32 ..
-rw-r--r-- 1 root root 1966 10月 18 20:32 clickhouse-config.xml
-rwxr-xr-x 1 root root 1740 10月 18 20:32 clickhouse-init.sh
-rw-r--r-- 1 root root 29057 10月 18 20:32 docker-compose.yml
-rw-r--r-- 1 root root 8188 10月 18 20:32 .env
四个文件全部生成:docker-compose.yml(36 个 service 定义,含按所选数据库裁剪后的启用项)、.env(约 220 个变量,_APP_HTTP_PORT="8102"、_APP_DB_ADAPTER="postgresql"、_APP_VERSION="2.5.0" 均已按参数写入)、clickhouse-config.xml 与 clickhouse-init.sh(被 compose 以 ./clickhouse-config.xml 相对路径挂载,必须与 compose 同目录)。
核对 .env 关键值:
grep -E '_APP_HTTP_PORT|_APP_HTTPS_PORT|_APP_DB_ADAPTER=|_APP_VERSION=' /opt/appwrite/appwrite/.env
实测回显:
_APP_DB_ADAPTER="postgresql"
_APP_DB_HOST="postgresql"
_APP_HTTP_PORT="8102"
_APP_HTTPS_PORT="8143"
_APP_VERSION="2.5.0"
四、定制部署配置(显式子网)
官方生成的 compose 里四个网络均未指定子网,Docker 会自动分配,容易与宿主其他环境冲突。必须改为显式子网(本环境槽位 30:10.89.30.0/24 起)。编辑 docker-compose.yml,找到文件末尾的 networks: 段,替换为:
networks:
gateway:
name: gateway
ipam:
config:
- subnet: 10.89.30.0/24
appwrite:
name: appwrite
ipam:
config:
- subnet: 10.89.31.0/24
runtimes:
name: runtimes
ipam:
config:
- subnet: 10.89.32.0/24
browser:
name: browser
ipam:
config:
- subnet: 10.89.34.0/24
⚠️ browser 网络没有用 10.89.33.0/24:实测该段已被本机先前部署的其他环境(Teable)占用,创建时会报
Pool overlaps with other one on this address space。子网规划前先docker network inspect $(docker network ls -q) --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}'排查存量占用。
宿主端口映射由 .env 变量驱动(${_APP_HTTP_PORT:-80}:80),.env 已是 8102,无需再改 compose 的 ports 段。
五、拉取镜像并启动服务栈
5.1 拉取全栈镜像
cd /opt/appwrite/appwrite
docker compose pull
全栈共 11 个镜像(docker compose config --images 实测输出):
appwrite/appwrite:2.5.0
appwrite/browser:0.3.6
appwrite/geo:0.3.2
appwrite/new:1.2.74-self-hosted
appwrite/postgres:0.1.0
clickhouse/clickhouse-server:26.4.3-alpine
ghcr.io/appwrite/autogravity:0.0.11
ghcr.io/open-runtimes/orchestrator/orchestrator:2.2.2
openruntimes/executor:1.1.2
redis:7.4.7-alpine
traefik:3.6
另有 5 个函数运行时镜像(openruntimes/node、php、python、ruby、flutter 等,合计约 4.7GB)会在首次创建函数时按需拉取,也可提前 docker pull openruntimes/node:v5-22 预热。
5.2 启动
docker compose up -d --remove-orphans
实测回显(节选,共 17 个服务):
Container appwrite-postgresql Healthy
Container appwrite-task-scheduler Starting
Container appwrite-realtime Starting
Container appwrite-task-interval Starting
Container appwrite Starting
Container appwrite-worker Starting
Container appwrite-task-scheduler Started
Container appwrite-realtime Started
Container appwrite-task-interval Started
Container appwrite Started
Container appwrite-traefik Starting
Container appwrite-traefik Started
Container appwrite-worker Started
Container appwrite-task-maintenance Started
⚠️ 若 runtimes 网络先前已被 Docker 以自动子网创建过(例如首轮 up 因子网冲突半途失败),compose 会复用旧网络而忽略显式子网。处理方法见第十章 FAQ 10.3。
六、验证部署
6.1 服务状态
docker compose ps --format 'table {{.Name}}\t{{.Status}}'
实测回显(约 40 秒后全部就绪):
NAME STATUS
appwrite Up 36 seconds (healthy)
appwrite-autogravity Up 43 seconds (healthy)
appwrite-browser Up 42 seconds
appwrite-clickhouse-1 Up 42 seconds (healthy)
appwrite-console Up 43 seconds (healthy)
appwrite-geo Up 42 seconds (healthy)
appwrite-mqtt Up 42 seconds (healthy)
appwrite-postgresql Up 42 seconds (healthy)
appwrite-realtime Up 36 seconds
appwrite-redis Up 42 seconds (healthy)
appwrite-task-interval Up 36 seconds
appwrite-task-maintenance Up 35 seconds
appwrite-task-scheduler Up 36 seconds
appwrite-traefik Up 36 seconds
appwrite-worker Up 35 seconds
exc1 Up 43 seconds (healthy)
orchestrator Up 43 seconds
6.2 健康检查
curl -s http://127.0.0.1:8102/v1/health \
-H 'X-Appwrite-Project: quzuo-demo' -H "X-Appwrite-Key: <项目API Key>"
实测回显:
{"name":"http","ping":0,"status":"pass"}
注意:/v1/health 在有项目上下文时可直接访问;不带项目头与 Key 时返回 401(2.5.0 的 health 命名空间要求 health.read scope):
{"message":"User (role: guests) missing scopes ([\"health.read\"])","code":401,"type":"general_unauthorized_scope","version":"2.5.0"}
版本确认(该端点需要管理员会话,见 8.2 节创建账号后获取):
curl -s http://127.0.0.1:8102/v1/health/version \
-b cookies.txt -H 'X-Appwrite-Project: console'
实测回显:
{"version":"2.5.0"}
6.3 控制台入口
curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://127.0.0.1:8102/
实测回显:
301 -> http://localhost/
浏览器访问 http://<宿主IP>:8102/ 即进入管理控制台登录页。
6.4 网络与路由核验
docker network inspect gateway appwrite runtimes browser --format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}'
实测回显:
gateway: 10.89.30.0/24
appwrite: 10.89.31.0/24
runtimes: 10.89.32.0/24
browser: 10.89.34.0/24
ip route get 192.168.1.62
实测回显(宿主默认路由未被容器网段劫持):
192.168.1.62 via 192.168.146.2 dev ens33 src 192.168.146.128 uid 0
cache
七、资源占用基线
docker stats --no-stream --format '{{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}'
实测回显(节选,空载稳态):
appwrite 363.3MiB / 31.3GiB 0.00%
appwrite-autogravity 84.99MiB / 31.3GiB 0.00%
appwrite-browser 246.7MiB / 31.3GiB 0.02%
appwrite-clickhouse-1 740.8MiB / 31.3GiB 5.35%
appwrite-console 124.1MiB / 31.3GiB 0.00%
appwrite-geo 39.39MiB / 31.3GiB 0.00%
appwrite-mqtt 67.12MiB / 31.3GiB 5.80%
appwrite-postgresql 183MiB / 31.3GiB 0.14%
appwrite-realtime 56.08MiB / 31.3GiB 0.07%
appwrite-redis 8.414MiB / 31.3GiB 2.11%
appwrite-task-interval 120.1MiB / 31.3GiB 0.00%
appwrite-traefik 26.41MiB / 31.3GiB 0.14%
appwrite-worker 116.8MiB / 31.3GiB 0.05%
exc1 (见 ps) healthy
orchestrator 9.453MiB / 31.3GiB 0.00%
17 个服务合计约 2.4GB 内存。内存紧张的宿主可接受 ClickHouse 偶发高占用;浏览器服务(247MB)仅在用到 Sites 渲染/浏览器截图功能时才有实际负载。
八、初始化管理账号与项目
8.1 创建 root 管理员
控制台首登需要一个 console 用户。2.5.0 默认 _APP_CONSOLE_WHITELIST_ROOT=enabled,第一个注册的账号即根管理员。用 API 创建(走 console 项目):
curl -s -X POST http://127.0.0.1:8102/v1/account \
-H 'X-Appwrite-Project: console' -H 'Content-Type: application/json' \
-d '{"userId":"unique()","email":"admin@example.com","password":"q1w2e3r4","name":"Admin"}'
实测回显(节选):
{"$id":"6ad4b81f372ea9.53613732","$createdAt":"2026-10-18T12:11:11.387+00:00","$updatedAt":"2026-10-18T12:11:11.387+00:00","name":"Admin","registration":"2026-10-18T12:11:11.370+00:00","status":true,"labels":[],"passwordUpdate":"2026-10-18T12:11:11.370+00:00","email":"admin@example.com","phone":"","emailVerification":false,...
8.2 登录建立会话
curl -s -c cookies.txt -X POST http://127.0.0.1:8102/v1/account/sessions \
-H 'X-Appwrite-Project: console' -H 'Content-Type: application/json' \
-d '{"userId":"unique()","email":"admin@example.com","password":"q1w2e3r4"}'
实测回显(节选):
{"$id":"6ad4b82140d9d34eb7f9","$createdAt":"2026-10-18T12:11:13.925+00:00","userId":"6ad4b81f372ea9.53613732","expire":"2026-11-17T12:11:13.902+00:00","provider":"email","providerUid":"admin@example.com",...
会话 Cookie 写入 cookies.txt(含 a_session_console),后续管理 API 均带 -b cookies.txt。
8.3 创建组织与项目
2.5.0 的项目归属组织(Organizations)。先建组织:
curl -s -b cookies.txt -X POST http://127.0.0.1:8102/v1/teams \
-H 'X-Appwrite-Project: console' -H 'Content-Type: application/json' \
-d '{"teamId":"quzuo-org","name":"Quzuo Org"}'
实测回显(节选):
{"$id":"quzuo-org","$createdAt":"2026-10-18T12:13:40.682+00:00","$updatedAt":"2026-10-18T12:13:40.682+00:00","name":"Quzuo Org","total":1,...
在组织下建项目(必须带 X-Appwrite-Organization 头,否则 401):
curl -s -b cookies.txt -X POST http://127.0.0.1:8102/v1/organization/projects \
-H 'X-Appwrite-Project: console' -H 'X-Appwrite-Organization: quzuo-org' \
-H 'Content-Type: application/json' \
-d '{"projectId":"quzuo-demo","name":"Quzuo Demo"}'
实测回显(节选):
{"$id":"quzuo-demo","$createdAt":"2026-10-18T12:13:46.808+00:00","name":"Quzuo Demo","teamId":"quzuo-org","region":"default",...
8.4 创建项目 API Key
curl -s -b cookies.txt -X POST http://127.0.0.1:8102/v1/organization/projects/quzuo-demo/keys \
-H 'X-Appwrite-Project: console' -H 'X-Appwrite-Organization: quzuo-org' \
-H 'Content-Type: application/json' \
-d '{"keyId":"docs-test-key","name":"docs-test-key","scopes":["project.read","usage.read","users.read","users.write","sessions.read","sessions.write","teams.read","teams.write","databases.read","databases.write","tables.read","tables.write","columns.read","columns.write","indexes.read","indexes.write","rows.read","rows.write","collections.read","collections.write","attributes.read","attributes.write","documents.read","documents.write","buckets.read","buckets.write","files.read","files.write","tokens.read","tokens.write","functions.read","functions.write","executions.read","executions.write","sites.read","sites.write","providers.read","providers.write","topics.read","topics.write","subscribers.read","subscribers.write","targets.read","targets.write","health.read"]}'
实测回显(节选,secret 仅创建时完整返回一次,务必立即保存):
{"$id":"docs-test-key","$createdAt":"2026-10-18T12:14:57.989+00:00","name":"docs-test-key","scopes":[...],"expire":null,"secret":"standard_8ac04ec4d6d3...(共171字符)",...}
拿到 Key 后即可按《Appwrite 2.5.0 API 使用详解》逐条验证业务 API。
九、日常运维
9.1 日志查看
docker compose logs appwrite --tail 5
实测回显(节选):
appwrite | http.method GET
appwrite | http.path /v1/health/version
appwrite | http.response.code 200
9.2 停止与启动
docker compose stop
实测回显(节选):
Container exc1 Stopped
Container appwrite-postgresql Stopped
Container appwrite-redis Stopped
docker compose start
实测回显(节选):
Container appwrite-realtime Started
Container appwrite-task-interval Started
Container appwrite-task-maintenance Started
启动后约 30 秒健康检查转绿,/v1/health 恢复 {"status":"pass"}。
9.3 数据备份要点
数据全部落在命名卷:appwrite-postgresql(主库)、appwrite-redis(缓存/队列)、appwrite-clickhouse(用量统计)、appwrite-uploads(文件存储)、appwrite-certificates(证书)等。升级/迁移前至少备份 postgresql 卷与 .env(内含 _APP_OPENSSL_KEY_V1 加密密钥,丢失将无法解密既有凭证数据)。
十、FAQ(实测排障沉淀)
10.1 安装器报 Failed to start containers
未挂载 docker.sock 的预期现象,配置文件已生成,忽略错误,改在宿主目录执行 docker compose up -d。若想让安装器直接代启动,需挂载 docker.sock 并保证容器内外路径一致(不推荐)。
10.2 安装器报 Warning: Undefined array key 1 in CLI.php
裸旗标(如 --no-start)不被 explode('=') 解析逻辑支持。该警告无副作用;安装器没有独立的不启动开关,没有 docker.sock 时它自然停在启动前一步。
10.3 网络报 Pool overlaps with other one on this address space
目标子网已被占用(本文实测 10.89.33.0/24 被先前部署的 Teable 占用)。用 docker network inspect $(docker network ls -q) --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}' 列出存量子网,换一段空闲的(如 10.89.34.0/24)。若旧网络已半途创建,先 docker compose down 并 docker network rm <旧网络> 再 up。
10.4 显式子网不生效(runtimes 网络落到自动网段)
compose 的网络若在编辑子网之前已被创建过(首轮 up 失败留下的残留),后续 up 会复用旧网络、忽略新子网配置。实测处置:docker compose stop openruntimes-executor orchestrator && docker network rm runtimes && docker network create --subnet 10.89.32.0/24 runtimes && docker compose up -d openruntimes-executor,执行器容器需 up -d --force-recreate openruntimes-executor 重建入网。其余三个网络因 compose down/up 会随栈重建,不受影响。
10.5 执行器容器 exc1 状态异常
runtimes 网络被删除重建后,exc1 仍挂在旧网络名上会失联。按 10.4 的最后一步 force-recreate 即可恢复 (healthy)。
10.6 管理项目 API 返回 401 general_unauthorized_scope
2.5.0 项目管理走组织端点 /v1/organization/projects,仅会话 + 组织头可用:请求须带 -b cookies.txt(console 会话)与 X-Appwrite-Organization: <orgId> 头。用项目 API Key 调管理端点会 401,属预期。
10.7 /v1/health/version 返回 401 missing scopes (["public"])
该端点不在项目 API Key 的 scope 白名单里(实测确认 public 不是合法 key scope),须用 console 管理员会话 + X-Appwrite-Project: console 访问。
10.8 重复执行安装器报目录已存在
/usr/src/code/appwrite 挂载目录非空时安装器拒绝覆盖(提示 contact support / use the update command)。备份旧目录后清空再生成,或直接改现有 .env 与 compose。
十一、参考链接
- 官方自托管安装指南:https://appwrite.io/docs/advanced/self-hosting/installation
- 官方 Docker Compose 参考仓库:https://github.com/appwrite/appwrite
- 环境变量总表:https://appwrite.io/docs/advanced/self-hosting/environment-variables
- 镜像仓库:https://hub.docker.com/r/appwrite/appwrite
- 参数细节:《Appwrite 2.5.0 配置参数详解》
- 初始化后的接口验证:《Appwrite 2.5.0 API 使用详解》