QD(也常被称为 Qiandao)是一个可以根据 HAR 请求编排定时任务的签到框架。官方 Compose 示例包含了大量可选参数,第一次部署时容易让人无从下手。实际上,如果服务器上已经有 Redis 和 Nginx Proxy Manager,只需要保留少量核心配置即可。
本文完成的部署结构如下:
Internet
|
v
Cloudflare / DNS
|
v
Nginx Proxy Manager :80/:443
|
| app-network
v
QD container :80 --------> Redis container :6379 (DB 1)
QD 不向宿主机映射端口。公网请求统一进入 Nginx Proxy Manager,再通过 Docker 内部网络访问 qd:80。
一、准备条件
本文假设服务器已经具备:
- Docker Engine 和 Docker Compose
- 一个正在运行的 Redis 容器
- 一个正在运行的 Nginx Proxy Manager 容器
- 一个已解析到服务器的域名,例如
qd.example.com - Redis、Nginx Proxy Manager 和 QD 使用同一个 Docker 网络,例如
app-network
先确认网络是否存在:
docker network ls
如果还没有公共网络,可以创建:
docker network create app-network
已有 Redis 和 Nginx Proxy Manager 时,不要重复创建网络,只需确认它们已经加入该网络:
docker network inspect app-network
二、准备部署目录
创建 QD 的独立目录:
mkdir -p /opt/docker/qd/config
cd /opt/docker/qd
其中 config 用于保存 SQLite 数据库等持久化数据。删除或丢失该目录会导致账号和任务数据丢失。
三、创建脱敏环境变量
在部署目录创建 .env:
REDIS_PASSWORD=请替换为你的Redis密码
COOKIE_SECRET=请替换为随机生成的长字符串
AES_KEY=请替换为另一个随机生成的长字符串
可以使用 OpenSSL 生成两个独立密钥:
openssl rand -hex 32
openssl rand -hex 32
不要继续使用示例中的 binux 等默认值。限制 .env 的读取权限:
chmod 600 .env
如果 Redis 密码含有 @、:、/、# 等 URL 特殊字符,需要先进行 URL 编码,否则 Redis 连接地址可能解析失败。为了避免这个问题,也可以使用只包含字母、数字、连字符和下划线的强随机密码。
四、编写 Compose 配置
创建 compose.yaml:
services:
qd:
image: qdtoday/qd:latest
container_name: qd
restart: unless-stopped
volumes:
- ./config:/usr/src/app/config
environment:
TZ: Asia/Shanghai
DOMAIN: qd.example.com
COOKIE_SECURE_MODE: "True"
COOKIE_SECRET: ${COOKIE_SECRET}
AES_KEY: ${AES_KEY}
REDISCLOUD_URL: redis://:${REDIS_PASSWORD}@redis:6379/1
networks:
- app-network
networks:
app-network:
external: true
name: app-network
这里有几个需要注意的地方:
redis是现有 Redis 的容器名。如果你的容器名不同,需要同步修改连接地址。/1表示使用 Redis DB 1,避免和已经使用 DB 0 的应用混在一起。- 配置中没有
ports,因此不会把 QD 的端口暴露到宿主机。 COOKIE_SECURE_MODE只应在网站已经通过 HTTPS 访问时启用。DOMAIN只填写域名,不要添加https://和路径。- Compose 文件不需要再声明
version: "3",新版 Docker Compose 已经不再需要该字段。
如果 Redis 没有设置密码,连接地址可以改为:
REDISCLOUD_URL: redis://redis:6379/1
五、启动 QD
先检查最终配置是否有效:
docker compose config --quiet
拉取镜像并启动:
docker compose pull
docker compose up -d
查看状态与日志:
docker compose ps
docker compose logs -f --tail=100
正常情况下,日志中会出现类似内容:
Queue Worker start...
Http Server started on 0.0.0.0:80
docker compose ps 只显示 80/tcp 是正常的。这是容器内部端口,并不代表宿主机的 80 端口被 QD 占用。只有看到类似 0.0.0.0:8923->80/tcp 时,才表示端口被映射到了宿主机。
六、配置 Nginx Proxy Manager
打开 Nginx Proxy Manager 管理页面,进入 Hosts -> Proxy Hosts -> Add Proxy Host。
在 Details 页面填写:
Domain Names: qd.example.com
Scheme: http
Forward Hostname / IP: qd
Forward Port: 80
Websockets Support: 开启
Block Common Exploits: 开启
在 SSL 页面填写:
SSL Certificate: 选择现有证书,或申请新的证书
Force SSL: 开启
HTTP/2 Support: 开启
保存后,Nginx Proxy Manager 会通过 app-network 访问 qd:80。这里不能填写 127.0.0.1,因为在 Nginx Proxy Manager 容器内部,127.0.0.1 指向的是它自己。
可以在服务器上测试:
curl -I https://qd.example.com
如果返回 HTTP/2 200 或 HTTP/1.1 200,说明 HTTPS 和反向代理均已正常工作。
七、首次登录
QD 没有预设的默认账号和密码。首次打开 https://qd.example.com 后,需要自行注册账号。
全新数据库中的第一个注册用户默认会成为管理员,因此正式开放域名前最好先完成管理员账号注册,并使用独立的强密码。
八、更新与备份
更新镜像:
cd /opt/docker/qd
docker compose pull
docker compose up -d
日常备份至少应包含:
/opt/docker/qd/config/
/opt/docker/qd/compose.yaml
/opt/docker/qd/.env
其中 .env 包含敏感信息,备份文件也应加密或限制访问权限。迁移部署时必须保留原来的 COOKIE_SECRET 和 AES_KEY,随意更换可能导致现有 Cookie 或加密数据无法继续使用。
九、常见问题
1. Redis 提示 NOAUTH Authentication required
说明 Redis 开启了密码认证,但 REDISCLOUD_URL 没有携带密码。检查连接地址是否为:
redis://:密码@redis:6379/1
2. Nginx Proxy Manager 返回 502
依次检查:
docker ps
docker network inspect app-network
docker logs --tail=100 qd
确认 QD 和 Nginx Proxy Manager 位于同一网络,并且代理目标是容器名 qd 和容器端口 80。
3. 签到任务出现 HTTP 521
任务请求中的 521 通常是目标网站的 WAF 或源站返回,并不等于 QD 服务部署失败。如果 QD 页面本身可以正常打开,应检查目标网站是否限制了服务器 IP、自动化请求、Cookie 或 User-Agent。
不要为了让任务显示成功而把成功断言改成 521,这只会掩盖真实的签到失败。
总结
复用现有 Redis 时,QD 的部署并不复杂:让 QD、Redis 和 Nginx Proxy Manager 加入同一个 Docker 网络,QD 使用容器名连接 Redis,Nginx Proxy Manager 再通过 qd:80 提供 HTTPS 入口即可。
这种方式不需要暴露额外的宿主机端口,服务入口更统一,后续备份和升级也更容易管理。