DailyTxT 2.6.4 Docker Compose 部署指南
Docker Compose 部署 DailyTxT 2.6.4(Go+Svelte 自托管加密日记):注册登录、JSON 加密落盘、多用户隔离与版本检查排障全流程实测
DailyTxT 2.6.4 Docker Compose 部署指南
目标:用 Docker Compose 部署 DailyTxT 2.6.4(Go + Svelte 自托管加密日记),完成首个用户注册、加密落盘验证、多用户隔离实测与版本检查端点排障,形成"部署 → 初始化 → 验证 → 运维"闭环。已在 Ubuntu 26.04.1 LTS(x86_64,Docker 29.9.2 / Compose v5.6.1)实测通过。
一、环境信息
- 操作系统:Ubuntu 26.04.1 LTS(x86_64)
- Docker:29.9.2(
docker --version实测);Docker Compose:v5.6.1(docker compose version实测) - DailyTxT:2.6.4(官方镜像
phitux/dailytxt:2.6.4,GitHub Releases 最新稳定版,发布 2026-10-10,查询日期 2026-11-01) - 应用内部端口:80(镜像内 nginx,
/api/*反代到同机 Go 后端 :8000);宿主映射端口:8137 - 数据目录:
/data(容器内),宿主 bind mount 到部署目录的./data - 部署目录:本文实测路径为工作区约定路径
/opt/data/quzuo/tmp/dailytxt,实际部署可任选目录(compose 内挂载用相对路径./data,与绝对路径无关) - Compose 项目名:
dailytxt-264-stack(name:显式声明,避免与其他项目同名互扰) - 自定义网络:
dailytxt-net,子网10.89.59.0/24 - 演示账号:日记用户
admin/q1w2e3r4;管理面板密码q1w2e3r4
二、镜像选型说明
DailyTxT 官方在 Docker Hub 发布多架构镜像(AMD64/ARM64),仓库 phitux/dailytxt,共 75 个 tag(查询日期 2026-11-01)。选型要点:
| tag 形态 | 示例 | 说明 |
|---|---|---|
| 稳定版数字 tag | 2.6.4 | 生产唯一推荐,与 GitHub Release 一一对应 |
latest | latest | 随发版漂移,官方 README 亦提醒按版本固定 |
-testing.N | 2.6.4-testing.2 | 官方明确标注非稳定版,仅测试用,勿上生产 |
解读:v2(Go 重写)与 v1(Python/Flask)镜像数据格式与环境变量不兼容,跨大版本升级必须按官方迁移流程处理(见十一、常见问题 11.5)。拉取与确认:
docker pull phitux/dailytxt:2.6.4
docker images phitux/dailytxt --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}}'
Digest: sha256:a55a38ca85790262d6e59b9d14a758d183d56a634f6023365f9c53c34620d046
Status: Downloaded newer image for phitux/dailytxt:2.6.4
phitux/dailytxt:2.6.4 a55a38ca8579 42.4MB
⚠️ 网络说明:本实验环境 docker pull 经宿主 Docker 守护进程配置的代理完成;若你的服务器直连 Docker Hub 缓慢,可为守护进程配置镜像加速或代理后重试(详见十一、常见问题 11.1 同类处理)。
三、前置条件
- 已安装 Docker Engine 与 Compose 插件(
docker compose version有输出即可); - 宿主端口 8137 未被占用:
ss -ltn | grep ':8137'
部署前实测无输出(端口空闲);占用则更换映射左端口。
- 已规划部署目录(本文
/opt/data/quzuo/tmp/dailytxt); - 服务器可访问 Docker Hub(拉镜像);若还需访问
hub.docker.comAPI(版本更新检查端点),注意应用运行时的出网能力(见 11.1)。
四、部署步骤
4.1 准备目录与 SECRET_TOKEN
mkdir -p /opt/data/quzuo/tmp/dailytxt/data
cd /opt/data/quzuo/tmp/dailytxt
export SECRET_TOKEN=$(openssl rand -base64 32)
echo "$SECRET_TOKEN" > secret_token.txt
SECRET_TOKEN 是后端签发/校验登录 JWT 的 HS256 密钥,官方要求用 openssl rand -base64 32 生成。本文将其写入 secret_token.txt 并在 compose 中以 ${SECRET_TOKEN} 引用,避免把密钥硬编码进 compose 文件(生产环境也可改用 .env 文件,compose 自动读取)。
4.2 编写 docker-compose.yml
/opt/data/quzuo/tmp/dailytxt/docker-compose.yml(在官方 compose 基础上固定版本 tag、显式项目名与子网、密钥改为变量注入):
name: dailytxt-264-stack
services:
dailytxt:
image: phitux/dailytxt:2.6.4
container_name: dailytxt-264-web
restart: unless-stopped
volumes:
- ./data:/data
environment:
- SECRET_TOKEN=${SECRET_TOKEN}
- INDENT=4
- ALLOW_REGISTRATION=true
- ADMIN_PASSWORD=q1w2e3r4
- LOGOUT_AFTER_DAYS=40
ports:
- "8137:80"
networks:
- dailytxt-net
networks:
dailytxt-net:
driver: bridge
ipam:
config:
- subnet: 10.89.59.0/24
逐项说明:
image: phitux/dailytxt:2.6.4:固定稳定版 tag(官方 compose 模板写的是2.x.x占位,必须替换);./data:/data:日记数据唯一持久化卷,/data是镜像VOLUME声明路径;SECRET_TOKEN=${SECRET_TOKEN}:从 shell 环境变量插值(4.1 已导出);INDENT=4:JSON 数据文件美化缩进,便于人工查看结构;ALLOW_REGISTRATION=true:仅初始化阶段开启,建好首个用户后建议改false(见 11.2 与《配置参数详解》);ADMIN_PASSWORD:管理面板口令(演示值q1w2e3r4);LOGOUT_AFTER_DAYS=40:登录 Cookie 有效期 40 天;ports: "8137:80":v2 内部端口是 80(v1 是 8000,升级时易踩坑);name:与自定义网络子网:多项目共存时防互删、防子网冲突。
4.3 启动栈
docker compose up -d
实测回显:
Network dailytxt-264-stack_dailytxt-net Creating
Network dailytxt-264-stack_dailytxt-net Created
Container dailytxt-264-web Creating
Container dailytxt-264-web Created
Container dailytxt-264-web Starting
Container dailytxt-264-web Started
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
dailytxt-264-web phitux/dailytxt:2.6.4 "/entrypoint.sh" dailytxt 1 second ago Up Less than a second 0.0.0.0:8137->80/tcp, [::]:8137->80/tcp
4.4 启动日志验证
docker compose logs --tail 20
实测回显(节选,后端横幅 + nginx 启动):
dailytxt-264-web | Indent: 4
dailytxt-264-web | Allow Registration: true
dailytxt-264-web | Base Path: /
dailytxt-264-web | ================
dailytxt-264-web |
dailytxt-264-web | dailytxt: 2026/11/01 11:16:07.012049 helpers.go:241: No users.json found, skipping old data check.
dailytxt-264-web | dailytxt: 2026/11/01 11:16:07.012211 main.go:151: Warning: ALLOWED_HOSTS is empty, CORS will not allow any cross-origin requests
dailytxt-264-web | dailytxt: 2026/11/01 11:16:07.013213 main.go:166: Server listening on :8000
dailytxt-264-web | 2026/11/01 11:16:07 [notice] 1#1: using the "epoll" event method
dailytxt-264-web | 2026/11/01 11:16:07 [notice] 1#1: nginx/1.31.6
dailytxt-264-web | 2026/11/01 11:16:07 [notice] 1#1: start worker processes
要点:Server listening on :8000 是 Go 后端(仅镜像内部使用),对外服务由 nginx 1.31.6 在 80 端口统一提供(静态资源 + /api/ 反代);ALLOWED_HOSTS is empty 警告表示不做跨域放行,单机自用属正常状态。
4.5 Web 与版本端点验证
curl -s -o /dev/null -w 'GET / -> %{http_code}\n' http://localhost:8137/
curl -s http://localhost:8137/api/version
GET / -> 200
{"current_version":"2.6.4","latest_overall_version":"2.6.4","latest_stable_version":"2.6.4"}
⚠️ 若 /api/version 返回 Request timeout:该端点会实时请求 hub.docker.com 检查新版本,服务器出网受限时必超时,修复方法见 11.1。
4.6 注册首个用户并写入第一篇日记
注册(此时 ALLOW_REGISTRATION=true):
curl -s -X POST http://localhost:8137/api/users/register \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}'
{"success":true}
登录(用 curl 的 cookie jar 维持会话,后续所有 API 调用都带 -b cookies.txt):
curl -s -c cookies.txt -X POST http://localhost:8137/api/users/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}'
{"available_backup_codes":-1,"migration_started":false,"username":"admin"}
curl -s -b cookies.txt http://localhost:8137/api/users/check
{"user_id":1,"username":"admin"}
写入 2026-11-01 的日记并回读:
curl -s -b cookies.txt -X POST http://localhost:8137/api/logs/saveLog \
-H 'Content-Type: application/json' \
-d '{"day":1,"month":11,"year":2026,"text":"# DailyTxT 实测\n端到端加密日记第一篇。","date_written":"2026-11-01"}'
{"history_available":true,"success":true}
curl -s -b cookies.txt 'http://localhost:8137/api/logs/getLog?year=2026&month=11&day=1'
{"date_written":"2026-11-01","files":[],"history_available":true,"pins":[],"tags":[],"text":"# DailyTxT 实测\n端到端加密日记第一篇。"}
4.7 加密落盘验证(核心特性)
登录成功后,服务器磁盘上应只有密文。检查数据目录:
find data -type f | sort
data/1/2026/11.json
data/1/settings.encrypted
data/1/tags.json
data/1/templates.json
data/users.json
head -c 400 data/1/2026/11.json
实测回显(节选):
{
"days": [
{
"date_written": "r4ZD9cisT91RdzoJHnn8lpLS_j2Kmi0ZrioyIUZaSP7p8Z-bPL8=",
"day": 1,
"text": "M5Ha0Qx_BNkER6AjPThbI99z55uWSyTSCF9edNbe2oeUpC9V5AvQiphybOD-hCsOOct6jNbeszCkXgJzyFffvxBZ9sRkAhpMOUPB-n-_ocBv9UD220biUzftqSiHOS_9qQ=="
}
]
}
解读:日记正文(text)与书写日期(date_written)都是 base64url 密文(ChaCha20-Poly1305),而 day、月份文件名、标签 id 等结构字段保持明文——这正是"服务端可索引搜索、内容不可读"的落盘形态。INDENT=4 让 JSON 结构可读,但不影响密文本身。用户口令在 users.json 中只存 Argon2id 哈希($argon2id$v=19$m=65536,t=5,p=6$...),详见《DailyTxT 2.6.4 配置参数详解》。
4.8 多用户与数据隔离实测
开启状态下注册第二个用户:
curl -s -X POST http://localhost:8137/api/users/register \
-H 'Content-Type: application/json' \
-d '{"username":"qzuo","password":"q1w2e3r4"}'
{"success":true}
curl -s -c cookies2.txt -X POST http://localhost:8137/api/users/login \
-H 'Content-Type: application/json' \
-d '{"username":"qzuo","password":"q1w2e3r4"}'
curl -s -b cookies2.txt 'http://localhost:8137/api/logs/getLog?year=2026&month=11&day=1'
{"available_backup_codes":-1,"migration_started":false,"username":"qzuo"}
{"date_written":"","files":[],"pins":[],"tags":[],"text":""}
解读:第二个用户登录成功但读到的 11 月 1 日是空条目——每个用户的数据目录(data/2/)与加密密钥完全独立,互相不可见。验证完毕后可用管理面板删除测试用户(口令为 ADMIN_PASSWORD):
curl -s -b cookies.txt -X POST http://localhost:8137/api/admin/delete-user \
-H 'Content-Type: application/json' \
-d '{"admin_password":"q1w2e3r4","user_id":2}'
{"success":true}
五、数据持久化说明
- 唯一需要持久化的路径是
/data,本文用 bind mount./data:/data;也可改用命名卷(docker volume create dailytxt-data后挂dailytxt-data:/data)。 /data内容:users.json(用户与 Argon2id 哈希、加密后的加密密钥)+ 每用户目录<user_id>/(YYYY/M.json按月日记、files/附件密文、tags.json、templates.json、settings.encrypted)。- 备份:直接打包
./data即可整机迁移;也可用应用内"备份 API"导出加密/解密 ZIP(见《DailyTxT 2.6.4 API 使用详解》)。 - 恢复:新环境用同一 compose + 同一
SECRET_TOKEN起服务,把备份的data放回挂载点即可;登录态 Cookie 的 JWT 校验依赖SECRET_TOKEN,换 token 只影响旧会话(见 11.3)。
六、环境变量表
官方 v2 环境变量全集(后端 settings.go/helpers.go 与 README 实查,查询日期 2026-11-01):
| 变量 | 默认值 | 说明 |
|---|---|---|
SECRET_TOKEN | 内置默认值 | JWT HS256 签名密钥,必改:openssl rand -base64 32 |
DATA_PATH | /data | 数据目录 |
INDENT | 无(紧凑) | JSON 落盘缩进空格数,设 4 便于人工查看 |
ALLOW_REGISTRATION | false | 是否允许公开注册;首个用户建好后建议关闭 |
ADMIN_PASSWORD | 无 | 管理面板口令(后端直接读取比对) |
LOGOUT_AFTER_DAYS | 40 | 登录 Cookie/JWT 过期天数 |
BASE_PATH | / | 子路径部署前缀(如 /dailytxt),由入口脚本改写前端资源路径 |
ALLOWED_HOSTS | 空 | CORS 允许的源列表(逗号分隔),空=不放行任何跨域 |
DEVELOPMENT | false | 开发模式(本地前后端分离联调用,生产勿开) |
HTTPS_PROXY | 无 | 非 DailyTxT 专属变量,Go 标准库自动识别;用于出网受限环境恢复版本检查(见 11.1) |
解读:与 v1(Flask 时代)相比环境变量几乎全部更换,v1→v2 升级必须重写 compose 的 environment 段(官方 Migration Instructions 原话),参数逐项详解见《DailyTxT 2.6.4 配置参数详解》。
七、配置参数说明
DailyTxT 没有外部配置文件,一切配置走环境变量 + 用户在线设置(管理面板/个人设置,密文存 settings.encrypted)。应用内两处与"配置"强相关:
- 登录会话:JWT(HS256,密钥即
SECRET_TOKEN)载荷含user_id、name、derived_key、exp四个字段,经Set-Cookie: token=...; HttpOnly; SameSite=Lax; Expires=...下发。实测一次登录的 Cookie 属性(LOGOUT_AFTER_DAYS=40,登录于 2026-11-01):
Set-Cookie: token=eyJhbGciOiJIUzI1NiIs...; Path=/; Expires=Fri, 11 Dec 2026 11:22:57 GMT; HttpOnly; SameSite=Lax
- 口令哈希参数:
users.json实测$argon2id$v=19$m=65536,t=5,p=6$<salt>$<hash>——内存 64MB、5 轮、并行度 6,是登录慢于普通 Web 应用(约 0.3-1 秒)的正常原因。
八、配置文件挂载
镜像内 nginx 配置位于 /etc/nginx/conf.d/default.conf,如需自定义(如上传大小、超时)可整文件覆盖挂载。镜像默认配置实测要点(docker exec dailytxt-264-web cat /etc/nginx/conf.d/default.conf 输出节选):
server {
listen 80;
root /usr/share/nginx/html;
client_max_body_size 0; # disable upload-size limit
location /api/ {
proxy_pass http://127.0.0.1:8000$request_uri;
proxy_read_timeout 6000s; # allow long-running exports/uploads
}
location /_app/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
try_files $uri /index.html; # SPA fallback
}
}
解读:上传体积在 nginx 层不限(client_max_body_size 0,官方前端限制单文件 500MB);API 反代超时 6000 秒配合大导出/大上传;对外加 TLS 与访问控制建议在前面再挂一层反向代理(Caddy/Traefik/Nginx 均可),并把 ports 收紧为 127.0.0.1:8137:80(官方 compose 模板即此写法)。
九、等价 docker run
compose 与单命令等价(实测):
docker run -d --name dailytxt-264-runtest \
-p 127.0.0.1:18137:80 \
-e SECRET_TOKEN="$SECRET_TOKEN" \
-e INDENT=4 \
-e ALLOW_REGISTRATION=true \
-e ADMIN_PASSWORD=q1w2e3r4 \
-e LOGOUT_AFTER_DAYS=40 \
-v /opt/data/quzuo/tmp/dailytxt/runtest-data:/data \
phitux/dailytxt:2.6.4
fac7e2bd65ed986a3b45d884879fd0d992b4e17e666d609c0a29894ab0821b66
GET / -> 200
验证通过(返回容器 ID、Web 首页 200),测试容器已用 docker rm -f dailytxt-264-runtest 清理。
十、常用运维命令
docker compose ps # 栈状态
docker compose logs -f dailytxt # 跟踪日志(后端横幅+nginx 访问日志)
docker compose restart # 重启应用(数据不丢)
docker compose down # 停栈删容器(卷在宿主目录,数据安全)
升级版本(先备份 ./data,官方 WARNING 要求):
cp -a data data-backup-$(date +%F)
sed -i 's|phitux/dailytxt:2.6.4|phitux/dailytxt:2.6.5|' docker-compose.yml # 目标版本以 Releases 实查为准
export SECRET_TOKEN=$(cat secret_token.txt)
docker compose pull && docker compose up -d
docker compose pull 实测回显(当前 tag 已最新):
Image phitux/dailytxt:2.6.4 Pulling
Image phitux/dailytxt:2.6.4 Pulled
升级后验证:curl -s http://localhost:8137/api/version(返回 current_version 即新值;latest_* 字段来自 Docker Hub 实时检查)。
十一、常见问题
11.1 /api/version 返回 "Request timeout"(排障实录)
现象:部署完成后执行 curl http://localhost:8137/api/version,15 秒后返回:
Request timeout
定位:/api/version 不是本地静态信息——后端会实时 http.Get("https://hub.docker.com/v2/repositories/phitux/dailytxt/tags") 比对最新版本(源码 helpers.go,查询日期 2026-11-01),普通端点有 15 秒超时。在容器内实测出网:
docker exec dailytxt-264-web nc -zv -w 5 192.168.1.62 7897; echo nc62=$?
docker exec dailytxt-264-web nc -zv -w 5 192.168.1.72 7897; echo nc72=$?
nc: 192.168.1.62 (192.168.1.62:7897): Operation timed out
nc62=1
192.168.1.72 (192.168.1.72:7897) open
nc72=0
该环境容器无法直连 hub.docker.com,但可达代理 192.168.1.72:7897。
解决:Go 标准库自动识别 HTTPS_PROXY 环境变量,在 compose 的 environment: 增加一行并重建:
- HTTPS_PROXY=http://192.168.1.72:7897
export SECRET_TOKEN=$(cat secret_token.txt) && docker compose up -d
curl -s http://localhost:8137/api/version
{"current_version":"2.6.4","latest_overall_version":"2.6.4","latest_stable_version":"2.6.4"}
0.49 秒返回,端点恢复。⚠️ 网络说明:本环境 GitHub/hub.docker.com 官方源直连与代理 192.168.1.62:7897 均超时,代理 192.168.1.72:7897 实测可用;不影响日记功能本身,仅影响"新版本检查"。
11.2 SECRET_TOKEN 未导出时 compose 告警
docker compose restart/pull 等命令也会解析 compose 文件,若 shell 未导出 SECRET_TOKEN 会告警:
level=warning msg="The \"SECRET_TOKEN\" variable is not set. Defaulting to a blank string."
restart 不会重建容器、环境变量不变,可忽略;但切勿在未导出该变量时执行 up -d——会用空字符串重建容器,导致所有已登录会话失效(见 11.3)。建议把密钥写入部署目录 .env 文件(SECRET_TOKEN=xxx),compose 自动读取,杜绝此坑。
11.3 轮换 SECRET_TOKEN 后旧登录全部失效
实测:以新 SECRET_TOKEN 重建后,用旧 Cookie 调认证接口:
curl -s -b cookies.txt http://localhost:8137/api/users/check -w '\nhttp=%{http_code}\n'
Unauthorized
http=401
重新登录即恢复正常。这是 JWT 签名密钥轮换的预期行为,升级/迁移时若不想踢掉所有用户,必须保持 SECRET_TOKEN 不变。
11.4 注册重复用户名返回 500 而非 400
实测对已存在用户再次注册:
Internal Server Error: username already exists (error 400)
HTTP 状态为 500。属后端把业务错误当内部错误透传(源码 users.go 将 Register 的业务 error 统一包成 500),脚本化注册时应按响应文本而非仅状态码判断"已存在"。
11.5 从 v1(1.0.x)升级的注意事项
官方 Migration Instructions(README,查询日期 2026-11-01):v2 是 Go 全重写,内部端口变为 80、环境变量几乎全换;沿用同一数据卷启动 v2 后,旧数据自动移入 data/old/ 子目录,每个"老用户"首次登录时自动完成解密-重加密迁移(秒级/用户);全部用户迁移确认后,可在管理面板或文件系统删除 old 目录。迁移前必须先备份整个数据目录;浏览器需清 DailyTxT 站点缓存,移动端 PWA 需删除重装。
十二、参考链接
- 官方仓库与 compose 模板:https://github.com/PhiTux/DailyTxT(docker-compose.yml / Dockerfile / docker-entrypoint.sh,查询日期 2026-11-01)
- 官方镜像:https://hub.docker.com/r/phitux/dailytxt/
- 加密与存储机制说明:README "About encryption and data storage"
- 迁移说明:README "Migration Instructions"
- 产品定位与选型对比:见本专栏《DailyTxT 介绍与选型指南》
- 参数逐项详解与配置实验:见本专栏《DailyTxT 2.6.4 配置参数详解》
- 全部 REST 端点实测:见本专栏《DailyTxT 2.6.4 API 使用详解》