Apprise 2.0 API Docker Compose 部署指南

用 Docker Compose 在单台服务器部署 Apprise API v2.0.2 通知网关:镜像选型(tag 无 v 前缀)、compose 全文、三目录持久化、环境变量表、配置文件挂载、等价 docker run、运维命令与 FAQ(全量实测)。

Apprise通知自托管DockerCompose2026/10/25

Apprise 2.0 API Docker Compose 部署指南

目标:用 Docker Compose 在单台服务器上部署 Apprise API v2.0.2 通知网关(官方镜像 caronc/apprise:2.0.2),含数据持久化、环境变量配置、发送验证、常用运维与升级方法。本文所有命令与回显均已在 Ubuntu 22.04.5 LTS(x86_64)+ Docker 29.9.2 + Docker Compose v5.6.1 环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(jammy),x86_64
  • 容器运行时:Docker Engine 29.9.2、Docker Compose 插件 v5.6.1
  • 部署目标:Apprise API v2.0.2(镜像 caronc/apprise:2.0.2,基础系统 Debian 13 trixie,内置 Python 3.14.9、Apprise 库 2.1.0)
  • 部署目录:/opt/apprise-compose(compose 文件与三个数据卷目录均在其下)
  • Compose 项目名:apprise-2.0.2-stack;容器名:apprise-2.0.2-server
  • 对外端口:8000(HTTP API 与 Web 配置管理器同端口)

二、镜像选型说明

Apprise API 官方只维护一个 Docker Hub 仓库 caronc/apprise,镜像内已打包好「nginx + gunicorn + Django」完整栈,开箱即用,是官方首推的部署形态。镜像标签规则的实测结论(2026-10-25 查询 Docker Hub):

标签说明
2.0.2当前最新稳定版(2026-10-24 推送),注意无 v 前缀
2 / latest浮动标签,当前同样指向 2.0.2
v2.0.0 / v1.5.4 等老版本标签带 v 前缀,新旧命名风格不一致
edge开发分支滚动构建,生产勿用

⚠️ 注意:写 caronc/apprise:v2.0.2 会报 manifest ... not found——2.0.x 系列标签不带 v 前缀,而 1.x/2.0.0 时代带前缀,升级老部署时最容易踩这个坑。生产环境建议像本文一样锁定具体版本号,不要用 latest。

拉取后镜像体积实测:

docker images caronc/apprise
IMAGE                  ID             DISK USAGE   CONTENT SIZE   EXTRA
caronc/apprise:2.0.2   6ae97e24b344        527MB          119MB   U

解压后占用 527MB 磁盘(内容 119MB),预留 1GB 磁盘足够。

三、前置条件

开始部署前确认以下条件满足:

  1. 已安装 Docker Engine(≥ 24)与 Compose v2 插件;
  2. 磁盘剩余空间 ≥ 1GB;
  3. 8000 端口未被占用(可用 ss -ltn | grep :8000 预查,被占用时改端口映射,见常见问题 Q6);
  4. 能访问 Docker Hub 拉取镜像(拉取超时见常见问题 Q1)。

确认 Docker 与 Compose 版本:

docker --version
docker compose version
Docker version 29.9.2, build a82e528
Docker Compose version v5.6.1

四、部署步骤

4.1 创建部署目录与数据卷目录

sudo mkdir -p /opt/apprise-compose/config /opt/apprise-compose/attach /opt/apprise-compose/plugin
cd /opt/apprise-compose

三个目录分别对应容器内 /config(通知通道配置)、/attach(通知附件)、/plugin(自定义通知插件)。

4.2 编写 docker-compose.yml

在 /opt/apprise-compose/docker-compose.yml 写入(全文实测可用):

name: apprise-2.0.2-stack

services:
  apprise:
    image: caronc/apprise:2.0.2
    container_name: apprise-2.0.2-server
    ports:
      - "8000:8000"
    environment:
      APPRISE_STATEFUL_MODE: simple
      APPRISE_WORKER_COUNT: "1"
      APPRISE_DEFAULT_FORMAT: text
      TZ: Asia/Shanghai
    volumes:
      - /opt/apprise-compose/config:/config
      - /opt/apprise-compose/attach:/attach
      - /opt/apprise-compose/plugin:/plugin
    restart: unless-stopped

逐项说明:

配置项取值说明
nameapprise-2.0.2-stackCompose 项目名,决定网络/卷等资源前缀
imagecaronc/apprise:2.0.2锁定稳定版,不用浮动标签
container_nameapprise-2.0.2-server固定容器名,便于运维命令定位
ports8000:8000宿主 8000 映射到容器 8000
APPRISE_STATEFUL_MODEsimple配置键直接对应 /config/{key}.cfg 纯文本文件,可读可手工编辑
APPRISE_WORKER_COUNT"1"gunicorn worker 数;默认 CPU×2+1,小规格机器显式调小
APPRISE_DEFAULT_FORMATtext通知正文默认按纯文本处理(可选 text/markdown/html)
TZAsia/Shanghai容器时区
volumes三目录挂载配置、附件、插件持久化到宿主
restartunless-stopped开机与异常退出自动拉起

💡 技术拓展:有状态存储策略 APPRISE_STATEFUL_MODE 三档对比——

模式配置键与文件的映射适用
hash键名经哈希映射到存储文件,目录不暴露键名(默认值)键名可能含敏感信息时
simple键名直接对应 {key}.cfg 文件小团队,追求可读可手工编辑
disabled关闭有状态,仅保留无状态 /notify纯转发场景,零存储

本文采用 simple 档:配置文件可读、可直接备份与手工修复。

4.3 启动并验证

cd /opt/apprise-compose
docker compose up -d
 Network apprise-202-stack_default Creating
 Network apprise-202-stack_default Created
 Container apprise-2.0.2-server Creating
 Container apprise-2.0.2-server Created
 Container apprise-2.0.2-server Starting
 Container apprise-2.0.2-server Started

⚠️ 注意:compose 项目名 apprise-2.0.2-stack 中的点号会被 Compose 规范化剔除,实际创建的网络名是 apprise-202-stack_default(docker compose config 可见 name: apprise-202-stack)。用 docker network ls 找不到带点的网络名是正常现象,不是部署失败。

确认容器状态与端口映射:

docker compose ps
NAME                   IMAGE                  COMMAND                  SERVICE   CREATED          STATUS          PORTS
apprise-2.0.2-server   caronc/apprise:2.0.2   "/opt/apprise/webapp…"   apprise   28 minutes ago   Up 28 minutes   0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp

健康检查(纯文本与 JSON 两种形式):

curl -s http://127.0.0.1:8000/status
curl -s -H "Accept: application/json" http://127.0.0.1:8000/status
OK
{"config_lock": false, "attach_lock": false, "stateful_enabled": true, "stateless_enabled": true, "degraded": false, "max_attachments": 6, "attach_size": 209715200, "status": {"persistent_storage": true, "can_write_config": true, "can_write_attach": true, "details": ["OK"]}, "privilege": "admin"}

stateful_enabled/stateless_enabled 均为 true、persistent_storage 为 true,说明双模通知与持久化卷都正常。浏览器访问 http://192.168.1.10:8000/ 打开 Web 配置管理器。

4.4 端到端发送验证

先保存一个有状态配置键 myalerts(指向一个 JSON Webhook 接收端),再通过它发通知。这里用本机 8433 端口的临时 HTTP 接收器充当通知目标(把下面脚本存为 /root/webhook_receiver.py,用 nohup python3 /root/webhook_receiver.py > /var/log/webhook-receiver.log 2>&1 & 后台运行):

from http.server import BaseHTTPRequestHandler, HTTPServer

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        l = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(l)
        print("RECEIVED path=%s body=%s" % (self.path, body.decode()), flush=True)
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"{}")
    def log_message(self, *a):
        pass

HTTPServer(("0.0.0.0", 8433), H).serve_forever()

保存配置键(json:// 是通用 JSON Webhook 通道,把通知以 JSON POST 到目标地址;192.168.1.10 为接收器所在机器的示例地址,换成你的实际地址,注意该地址需从容器内可达——接收器在宿主机上时用宿主局域网 IP,不能用 127.0.0.1,那指向容器自身):

curl -s -X POST -H "Content-Type: application/json" \
  -d '{"urls": "json://192.168.1.10:8433/hook"}' \
  http://127.0.0.1:8000/add/myalerts
{"error": null}

通过该配置键发送一条 markdown 格式通知:

curl -s -X POST "http://127.0.0.1:8000/notify/myalerts?format=markdown" \
  --data-urlencode "body=**B2 持久化验证**:容器重启后通知通道正常"
2026-10-25 03:12:06,618 - INFO - Notifying 1 service(s).
2026-10-25 03:12:06,626 - INFO - Sent JSON POST notification.

接收器日志确认投递内容:

tail -1 /var/log/webhook-receiver.log
RECEIVED path=/hook body={"version": "1.0", "title": "", "message": "**B2 持久化验证**:容器重启后通知通道正常", "attachments": [], "type": "info"}

至此部署完成:8000 端口对外提供 API 与 Web 管理器,通知可正常投递。

五、数据持久化说明

三个挂载目录的分工与实测落盘形态:

宿主目录容器内内容
/opt/apprise-compose/config/config有状态配置(每键一个 {key}.cfg + 标记文件 + store/ 状态存储区)
/opt/apprise-compose/attach/attach通知附件上传
/opt/apprise-compose/plugin/plugin自定义通知插件(Python 文件)

4.4 保存配置键后,宿主侧实际落盘:

ls -la /opt/apprise-compose/config/
cat /opt/apprise-compose/config/myalerts.cfg
total 16
drwxr-xr-x    3 1000     1000          4096 Oct 25 03:41 .
drwxr-xr-x    6 root     root          4096 Oct 25 02:47 ..
-rw-------    1 1000     1000             0 Oct 25 02:47 .auth.guard
-rw-------    1 1000     1000             0 Oct 25 03:11 .myalerts.created
-rw-------    1 1000     1000            86 Oct 25 03:11 myalerts.cfg
drwxr-xr-x    3 1000     1000          4096 Oct 25 02:48 store
json://192.168.1.10:8433/hook?method=POST&overflow=upstream&retry=0&wait=0.5&optional=no

要点解读:

  • myalerts.cfg 是纯文本 Apprise URL 列表(每行一条),可直接用编辑器修改,权限 600。
  • 文件属主显示为 1000:1000——容器内运行用户是 apprise(uid 1000),宿主侧若无同名用户则显示数字。宿主上直接编辑后注意保持该属主,否则容器内可能读不到。
  • .myalerts.created 是键创建标记、.auth.guard 是认证保护标记、store/ 是发送状态存储区,均属正常运行产物,不要手工删除。

实测验证持久化:执行 docker compose down 再 docker compose up -d(命令回显见第十章),配置键 myalerts 完整保留、可直接继续发通知——配置安全取决于宿主目录而非容器生命周期。

六、环境变量表

Apprise API 服务端全部由环境变量配置,compose 的 environment: 段注入。本节列出部署最常用的变量(完整清单与全部默认值见本专栏《Apprise API 2.0 配置参数详解》):

环境变量默认值本文取值说明
APPRISE_STATEFUL_MODEhashsimple有状态存储策略:hash/simple/disabled
APPRISE_STATELESS_MODEenabled(默认)无状态 /notify 开关
APPRISE_WORKER_COUNTCPU×2+11gunicorn worker 数
APPRISE_WORKER_TIMEOUT300(默认)worker 超时秒数
APPRISE_DEFAULT_FORMAT空text通知正文默认格式:text/markdown/html
APPRISE_ATTACH_SIZE200(默认)附件总大小上限(MB)
APPRISE_MAX_ATTACHMENTS6(默认)单请求附件数上限
APPRISE_CONFIG_DIR镜像内置 /config(默认)配置目录(官方镜像已内置,无需显式声明)
APPRISE_ATTACH_DIR镜像内置 /attach(默认)附件目录(同上)
APPRISE_PLUGIN_PATHS镜像内置 /plugin(默认)插件扫描路径(同上)
APPRISE_AUTH_REQUIREDno(默认)是否启用全局 Basic Auth(yes/no)
APPRISE_USER / APPRISE_PASSWORD空(按需)全局管理员账号密码
APPRISE_ADMINyes(默认)是否启用 Web 配置管理器
ALLOWED_HOSTS*(默认)允许的 Host 头,生产建议改为实际域名
TZEtc/UTCAsia/Shanghai时区

⚠️ 注意:APPRISE_CONFIG_DIR 等三个路径变量在官方镜像 Dockerfile 中已内置,容器内实测可见——即使 compose 不显式声明也生效:

docker exec apprise-2.0.2-server env | grep APPRISE | sort
APPRISE_ATTACH_DIR=/attach
APPRISE_CONFIG_DIR=/config
APPRISE_DEFAULT_FORMAT=text
APPRISE_PLUGIN_PATHS=/plugin
APPRISE_STATEFUL_MODE=simple
APPRISE_WORKER_COUNT=1

生产环境建议补开全局认证(演示账号 admin / q1w2e3r4):

    environment:
      APPRISE_AUTH_REQUIRED: "yes"
      APPRISE_USER: admin
      APPRISE_PASSWORD: q1w2e3r4

七、配置参数说明

本文 compose 用到的 4 个显式变量:

  1. APPRISE_STATEFUL_MODE=simple:选择 simple 后,配置键与 /config/{key}.cfg 一一对应,便于备份(直接 tar 打包 config 目录)与灾难恢复(把文件放回即可)。
  2. APPRISE_WORKER_COUNT=1:单容器单核小规格部署时,默认值 CPU×2+1 会拉起过多 gevent worker、白白占内存;1~2 个 worker 足够支撑告警类低频流量。大流量再按 CPU 核数上调。
  3. APPRISE_DEFAULT_FORMAT=text:未显式声明格式的通知按纯文本处理,避免调用方漏传 format 时行为不一致。
  4. TZ=Asia/Shanghai:影响通知模板时间戳与日志时间。

修改任何环境变量后,需要 docker compose up -d 重建容器才生效(restart 不重读 compose 文件),完整参数语义与调优见《Apprise API 2.0 配置参数详解》。

八、配置文件挂载

simple 模式下配置目录是纯文本文件,因此支持「绕开 API、直接挂配置」的用法:把预先写好的 {key}.cfg 放进 ./config 目录即可被服务读取。例如手工创建:

echo 'json://192.168.1.10:8433/hook' | sudo tee /opt/apprise-compose/config/direct.cfg
sudo chown 1000:1000 /opt/apprise-compose/config/direct.cfg
sudo chmod 600 /opt/apprise-compose/config/direct.cfg

通过 API 读回验证(无需重启,请求时实时读盘):

curl -s http://127.0.0.1:8000/json/urls/direct
{"tags": [], "urls": [{"id": "0b765814", "service_name": "JSON", "enabled": true, "url": "json://192.168.1.10:8433/hook?method=POST&overflow=upstream&retry=0&wait=0.5&optional=no", "retry": 0, "optional": false, "tags": [], "tag_details": [], "template": {}}]}

⚠️ 注意:手工写入的文件属主必须是容器内 apprise 用户的 uid 1000(chown 1000:1000),权限建议 600;属主不对时 API 读取会报权限错误或读不到配置。批量迁移配置时此方式比逐条调 API 高效。

九、等价 docker run

不用 Compose 时,与本文 compose 文件完全等价的单命令形态:

docker run -d --name apprise-2.0.2-server \
  -p 8000:8000 \
  -e APPRISE_STATEFUL_MODE=simple \
  -e APPRISE_WORKER_COUNT=1 \
  -e APPRISE_DEFAULT_FORMAT=text \
  -e TZ=Asia/Shanghai \
  -v /opt/apprise-compose/config:/config \
  -v /opt/apprise-compose/attach:/attach \
  -v /opt/apprise-compose/plugin:/plugin \
  --restart unless-stopped \
  caronc/apprise:2.0.2

二者选其一即可。Compose 的优势在于配置即代码(环境变量、卷、重启策略都在 yml 里可评审、可版本化),升级与重建只需 up -d;docker run 适合一次性临时验证。

十、常用运维命令

以下命令均在 /opt/apprise-compose 目录下执行,回显为实测结果。

实时跟踪日志:

docker compose logs -f
apprise-2.0.2-server  | 2026-10-25 11:12:06,618 [INFO] apprise: Notifying 1 service(s).
apprise-2.0.2-server  | 2026-10-25 11:12:06,626 [INFO] apprise: Sent JSON POST notification.
apprise-2.0.2-server  | 2026-10-25 11:12:06,627 [INFO] django: NOTIFY -  - Delivered Notification(s) - KEY: myalerts

重启服务(不重读 compose 文件):

docker compose restart
 Container apprise-2.0.2-server Restarting
 Container apprise-2.0.2-server Started

停止并清理(数据卷目录保留在宿主,配置不丢):

docker compose down
 Container apprise-2.0.2-server Stopping
 Container apprise-2.0.2-server Stopped
 Container apprise-2.0.2-server Removing
 Container apprise-2.0.2-server Removed
 Network apprise-202-stack_default Removing
 Network apprise-202-stack_default Removed

重新拉起:

docker compose up -d
 Network apprise-202-stack_default Creating
 Network apprise-202-stack_default Created
 Container apprise-2.0.2-server Creating
 Container apprise-2.0.2-server Created
 Container apprise-2.0.2-server Starting
 Container apprise-2.0.2-server Started

进容器排查(镜像基于 Debian 13,自带 curl/python3,无 wget):

docker exec -it apprise-2.0.2-server /bin/bash

升级版本:修改 yml 中 image 标签后拉取并重建(当前已是最新时的实测回显):

docker compose pull
docker compose up -d
 Image caronc/apprise:2.0.2 Pulling
 Image caronc/apprise:2.0.2 Pulled

备份配置(纯文本目录直接打包即可):

sudo tar czf /root/apprise-config-$(date +%F).tar.gz -C /opt/apprise-compose config

十一、常见问题

Q1:docker compose pull 拉取镜像超时或失败? A:国内服务器直连 Docker Hub 不稳定。方案一配置镜像加速器(/etc/docker/daemon.json 加 registry-mirrors 后 systemctl restart docker);方案二给 Docker 守护进程配 HTTP 代理(/etc/docker/systemd/ 下 drop-in 注入 HTTP_PROXY/HTTPS_PROXY 环境变量)。改完重试 docker compose pull。

Q2:拉取报 manifest for caronc/apprise:v2.0.2 not found? A:2.0.x 系列标签不带 v 前缀,正确写法是 caronc/apprise:2.0.2。注意老版本(v2.0.0、v1.5.4)反而带前缀,命名风格不一致,以 Docker Hub 标签页为准。

Q3:docker network ls 里找不到 apprise-2.0.2-stack_default? A:Compose 会规范化项目名(剔除点号等特殊字符),本文项目实际网络名是 apprise-202-stack_default。可用 docker compose config 查看规范化后的项目名,属正常行为。

Q4:通知 URL 里的目标主机名报 Unparseable URL 类错误? A:实测发现 Apprise URL 解析器对某些含多段点号的非标主机名(如内部测试机名)解析失败。把主机名换成 IP 地址或标准 FQDN(如 hooks.example.com)即可正常解析投递;生产环境目标地址建议一律用标准域名或 IP。

Q5:改了 compose 文件里的环境变量,重启后不生效? A:docker compose restart 只重启进程、不重读 yml。必须 docker compose up -d,Compose 检测到配置变化后自动重建容器。

Q6:8000 端口被占用? A:改 ports 映射左侧端口,如 "18000:8000",然后 docker compose up -d;调用方相应改访问端口。

十二、参考链接