Appwrite Docker Compose 部署指南

基于官方镜像内置安装器生成配置并以 Docker Compose 实测部署 Appwrite 2.5.0 全栈(17 服务/11 镜像):显式子网 10.89.30.0/24 规划、宿主端口 8102 映射、启动与健康验证、根账号/组织/项目/API Key 初始化、资源占用基线,以及地址池冲突、网络重建等 8 条实测排障 FAQ。

AppwriteAppwriteBaaS2026/10/18

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 / ComposeDocker 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
appwriteAPI 核心appwrite
appwrite-consoleWeb 管理控制台appwrite-console
appwrite-realtime实时推送appwrite-realtime
appwrite-worker异步任务 workerappwrite-worker
appwrite-task-maintenance / interval / scheduler三类定时任务appwrite-task-*
postgresql主数据库(可换 mariadb/mongodb)appwrite-postgresql
redis缓存/队列/发布订阅appwrite-redis
clickhouse用量统计与执行日志分析appwrite-clickhouse-1
appwrite-mqttRealtime MQTT 通道appwrite-mqtt
appwrite-geoIP 地理查询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。

十一、参考链接