dayGLANCE 5.9.0 Docker Compose 部署指南

用 Docker Compose 把 dayGLANCE 5.9.0 部署为自托管服务的实测指南:官方 ghcr 镜像选型与 digest 钉扎、部署与验证、无状态持久化口径、WEBDAV_PROXY_BLOCK_PRIVATE 行为实测、等价单命令与常用运维命令。

dayGLANCEdayGLANCE任务管理2026/10/23

dayGLANCE 5.9.0 Docker Compose 部署指南

目标:用 Docker Compose 把 dayGLANCE 5.9.0(隐私优先的个人日规划与时间块工具)部署为可常驻、可升级、可自愈的自托管服务,覆盖镜像选型、部署、环境变量、数据持久化口径、等价单命令与常用运维命令。全部命令与回显均在 Ubuntu 22.04 + Docker 29.8.1 实测取得,逐条照抄即可复现。软件定位见 《dayGLANCE 5.9.0 介绍与选型指南》;非容器化安装见 《Ubuntu 22.04 安装 dayGLANCE 5.9.0 指南》。

一、环境信息

本文实测环境(全部命令与回显在这套环境取得):

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Docker Engine:29.8.1;Docker Compose:v5.5.1(v2 语法插件)
  • 部署形态:单服务 compose 项目,无数据库、无外部依赖
  • 镜像:ghcr.io/krelltunez/dayglance:latest(v5.9.0,amd64,压缩体约 195 MB)
  • 实测宿主端口:8131(映射容器 80;官方示例默认 6767,两者仅是宿主端口差异)
  • 验证地址:http://localhost:8131/(首页 200,标题 dayGLANCE)
  • 版本实查:GitHub Releases/releases.atom 显示最新稳定版 v5.9.0(2026-10-15 发布,查询日期 2026-10-22)

💡 说明:dayGLANCE 官方镜像内含两个进程——Nginx(托管静态页面与安全响应头,监听 80)和 Node.js 同步代理(监听容器内 127.0.0.1:3001,负责转发 WebDAV/日历请求)。整个实例无状态:所有用户数据存浏览器 localStorage,服务器侧没有数据库也没有必须持久化的目录,这是它与多数自托管应用最大的不同。

二、镜像选型说明

候选镜像结论依据
ghcr.io/krelltunez/dayglance:latest采用官方唯一维护渠道(GitHub Container Registry),与官方文档/README 推荐一致
Docker Hub 同名镜像不采用官方未发布 Docker Hub 仓库,第三方镜像无供应链保障
自行构建备选仓库含 Dockerfile(node:22-alpine 构建 + nginx:alpine 运行),仅镜像供应链受限时考虑

镜像事实(docker inspect 实测):架构 amd64(官方同时构建 arm64,树莓派/ARM 服务器可用,拉取时自动选择)、入口 /start.sh(先拉起 Node 代理再前台运行 Nginx)、暴露端口 80/tcp、内置 Nginx 1.31.7。

版本标签有个关键事实需要特别注意:ghcr.io 上该镜像的语义化版本标签只发到 2.12.0,此后的版本(含 v5.9.0)只随 latest 标签分发(https://ghcr.io/v2/krelltunez/dayglance/tags/list 实查,查询日期 2026-10-22)。因此:

  • 想钉扎 v5.9.0 → 用 digest 钉扎:ghcr.io/krelltunez/dayglance@sha256:4537e3206e3cf4223b064ace01d877d653c45cb0251bb6cc4a7eb7c141d557dd(本批实测拉取的 latest 所指 digest,可用 docker inspect --format '{{index .RepoDigests 0}}' ghcr.io/krelltunez/dayglance:latest 自行核验);
  • 想跟随周更 → 用 latest,升级走 docker compose pull && docker compose up -d。

三、前置条件

  1. Ubuntu 22.04 服务器(或任意能跑 Docker 的 x86_64/arm64 主机),具备 sudo 权限;

  2. Docker Engine 与 Compose 插件:

    docker --version && docker compose version
    

    实测回显:

    Docker version 29.8.1, build 4a63305
    Docker Compose version v5.5.1
    
  3. 宿主机目标端口未被占用(本文用 8131,可用 ss -ltn | grep 8131 自查,无输出即空闲);

  4. 公网部署需自备反向代理与 HTTPS(见十、常见问题 Q3)。

四、部署步骤

4.1 编写 docker-compose.yml

建立部署目录并写入 compose 文件(name: 显式指定项目名,避免目录名变动导致项目漂移;宿主端口按需修改,官方示例用 6767):

mkdir -p /opt/dayglance-compose && cd /opt/dayglance-compose
cat > docker-compose.yml <<'EOF'
name: dayglance

services:
  dayglance:
    image: ghcr.io/krelltunez/dayglance:latest
    container_name: dayglance
    restart: unless-stopped
    ports:
      - "8131:80"
EOF

配置逐项说明:

  • image:官方 ghcr 镜像;要钉版本见第二节的 digest 写法;
  • restart: unless-stopped:宿主机重启或进程崩溃后自动拉起(手动 stop 的除外);
  • ports: "8131:80":宿主 8131 → 容器 80,容器内端口固定为 80 不要改;
  • 无需 volumes、无需 environment——该镜像无状态、无必填变量(可选变量见第六节)。

4.2 启动

docker compose up -d

实测回显:

 Container dayglance-590-web  Creating
 Container dayglance-590-web  Created
 Container dayglance-590-web  Starting
 Container dayglance-590-web  Started

(实测环境的 compose 项目名为 dayglance-590-stack,并显式指定了 container_name: dayglance-5.9.0-web,故回显容器名为 dayglance-5.9.0-web;按 4.1 的文件执行时容器名为 dayglance,行为一致。)

4.3 状态确认

docker compose ps

实测回显:

NAME                  IMAGE                                 COMMAND                   SERVICE     CREATED          STATUS          PORTS
dayglance-5.9.0-web   ghcr.io/krelltunez/dayglance:latest   "/docker-entrypoint.…"   dayglance   11 minutes ago   Up 11 minutes   0.0.0.0:8131->80/tcp, [::]:8131->80/tcp

4.4 访问验证

curl -s -o /dev/null -w "首页 HTTP %{http_code}\n" http://localhost:8131/
curl -s http://localhost:8131/ | grep -o "<title>[^<]*</title>"
curl -s -w "\n代理缺参 HTTP %{http_code}\n" http://localhost:8131/api/webdav-proxy/

实测回显:

首页 HTTP 200
<title>dayGLANCE</title>
{"error":"Missing url parameter"}
代理缺参 HTTP 400

逐项解读:首页 200 且标题正确说明 Nginx 托管的静态应用正常;/api/webdav-proxy/ 缺参返回 400 JSON,说明镜像内置的 Node 同步代理也已就绪。浏览器打开 http://<服务器IP>:8131/ 即可开始使用,按 ? 查看快捷键、按 N 建第一条任务。

查看启动日志确认两进程先后就绪:

docker compose logs --tail 5 dayglance

实测回显(节选,访问日志随请求增长):

dayglance-5.9.0-web  | 10.89.59.1 - - [22/Oct/2026:18:22:49 +0000] "GET /api/calendar-proxy/?url=http%3A%2F%2F10.89.59.2%2Ftest.ics HTTP/1.1" 200 252 "-" "curl/7.81.0" "-"
dayglance-5.9.0-web  | 10.89.59.1 - - [22/Oct/2026:18:22:49 +0000] "GET /api/webdav-proxy/?url=http%3A%2F%2F10.89.59.2%2Fhello.txt HTTP/1.1" 200 36 "-" "curl/7.81.0" "-"

五、数据持久化说明

结论先行:服务器侧没有需要持久化的数据,compose 文件不需要任何 volumes。(官方自托管文档口径:"dayGLANCE stores all user data locally in the browser (localStorage). The container itself is stateless — there's nothing to back up on the server side.",2026-10-22 查询)

由此带来的运维口径:

  • 升级/重建容器不丢数据:数据在浏览器,容器随时可删可换;
  • 清浏览器数据 = 清数据:换浏览器或换设备默认从零开始;
  • 真正的备份在同步通道:给应用配置 WebDAV/Nextcloud 同步(Settings → Cloud Sync)后,数据会持续写入你自己的网盘/服务器,并可用应用内自动备份(小时/天/周频率)远端存档;同步文件大小上限由中间层决定——官方镜像内 Nginx 未放开请求体限制(沿用默认 1 MB,实测证据见第七节);
  • 端到端加密可选:同步数据可在应用内开启 AES-256-GCM 加密,密钥不出设备。

六、环境变量表

镜像仅支持一个环境变量,控制同步代理对私网/局域网目标的放行策略:

变量取值默认行为(实测)
WEBDAV_PROXY_BLOCK_PRIVATE未设置 / 0 / false✅ 默认允许把 WebDAV/日历同步指向私网目标(NAS 192.168.x.x、内网 10.x、Tailscale 100.64/10 等)——自托管的本意
同上1 / true—拒绝私网/局域网目标,与官方托管版行为一致;云元数据端点(169.254.169.254)等保留网段无论开关一律拒绝

两个状态的实测证据。默认状态(未设置),私网目标 200 正常回显:

curl -s -w "\n[%{http_code}]\n" "http://localhost:8131/api/webdav-proxy/?url=http%3A%2F%2F10.89.59.2%2Fhello.txt"

实测回显(目标存在时返回文件内容;此处目标为固定件地址,内容节选):

fixture-for-webdav-proxy

[200]

开启封锁后的对照实例(-e WEBDAV_PROXY_BLOCK_PRIVATE=1 启动),同一私网目标被拒:

curl -s -w "\n[%{http_code}]\n" "http://localhost:8133/api/webdav-proxy/?url=http%3A%2F%2F10.89.59.2%2Fhello.txt"

实测回显:

{"error":"Private/reserved addresses are not allowed"}
[403]

且启动日志出现声明行:

[proxy] WEBDAV_PROXY_BLOCK_PRIVATE set — private/LAN targets will be refused
Proxy server listening on 127.0.0.1:3001

云元数据端点在两种状态下都被拒(实测):

curl -s -w "\n[%{http_code}]\n" "http://localhost:8131/api/webdav-proxy/?url=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2F"

实测回显:

{"error":"Private/reserved addresses are not allowed"}
[403]

⚠️ 注意:若实例可能被不可信的人访问,建议开启 WEBDAV_PROXY_BLOCK_PRIVATE=1——否则该代理会成为把请求中继进你内网的跳板。compose 用法:

    environment:
      - WEBDAV_PROXY_BLOCK_PRIVATE=1

七、配置参数说明

镜像内置行为无需(也不能通过环境变量)调整,但值得知道参数在哪、出问题查什么:

  • 容器内 Nginx(/etc/nginx/conf.d/default.conf,可用 docker exec dayglance cat /etc/nginx/conf.d/default.conf 查看):静态托管 + 安全响应头(CSP、HSTS、X-Frame-Options 等)、/api/ 反代到 127.0.0.1:3001(读/连超时 60s/30s;未配置 client_max_body_size,沿用 Nginx 默认 1 MB 请求体上限)、sw.js 与 manifest.webmanifest 强制不缓存(PWA 升级保障)、静态资源一年强缓存;
  • 容器内代理进程(/app/docker/proxy-server.mjs):固定监听 127.0.0.1:3001,支持方法 GET/PUT/DELETE/MKCOL/PROPFIND/OPTIONS(WebDAV)与 GET(日历),鉴权头经 X-WebDAV-Auth/X-Calendar-Auth 透传为目标站点的 Authorization;
  • 宿主侧可调的只有端口与重启策略(compose 的 ports/restart),以及反向代理层的 TLS 与认证。

请求体上限值得单独实测一遍——它决定了同步通道能携带多大的数据。生成 2 MB 测试体并经代理上传:

dd if=/dev/zero of=big2m.bin bs=1M count=2 2>/dev/null   # 生成 2 MB 测试文件
curl -s -X PUT --data-binary @big2m.bin "http://localhost:8131/api/webdav-proxy/?url=http%3A%2F%2F10.89.59.2%2Fhello.txt"

实测回显(Nginx 在请求进入代理前直接拦截):

<html>
<head><title>413 Request Entity Too Large</title></head>
<body>
<center><h1>413 Request Entity Too Large</h1></center>
<hr><center>nginx/1.31.7</center>
</body>
</html>

Nginx 错误日志同步记录了拒绝原因(docker compose logs dayglance | grep "too large"):

2026/10/23 00:40:03 [error] 11#11: *97 client intended to send too large body: 2097152 bytes, client: 10.89.59.1, server: localhost, request: "PUT /api/webdav-proxy/?url=http%3A%2F%2F10.89.59.2%2Fhello.txt HTTP/1.1", host: "localhost:8131"

💡 说明:dayGLANCE 的同步内容是纯文本任务记录(JSON),正常远小于 1 MB,该默认上限不影响常规使用;只有经代理传大附件时才需要关注,处置见十一、Q5。

八、配置文件挂载

无必需挂载。 该镜像设计为完全无状态(见第五节),官方也未提供自定义配置文件的注入口。若确需覆盖容器内 Nginx 配置,可以用 bind mount 替换 /etc/nginx/conf.d/default.conf,但这属于偏离官方镜像契约的自定义操作,升级镜像后可能失效,本文不推荐、不做为标准步骤。需要深度定制(如统一企业网关出口)时,更稳妥的路线是按 《Ubuntu 22.04 安装 dayGLANCE 5.9.0 指南》 方案 A 自行构建托管,配置完全自持。

九、等价 docker run

不使用 compose 时,一条命令等价部署(实测启动过的形态):

docker run -d \
  --name dayglance \
  --restart unless-stopped \
  -p 8131:80 \
  ghcr.io/krelltunez/dayglance:latest

实测回显(启动即输出容器 ID):

03b020f5b35e4ad4a00ebf003bd54a40938ce9ee0a68a3a31ef0924494673036

带封锁开关的等价形态(实测对照实例):

docker run -d --name dayglance-blockprivate -p 8133:80 \
  -e WEBDAV_PROXY_BLOCK_PRIVATE=1 \
  --restart unless-stopped \
  ghcr.io/krelltunez/dayglance:latest

两种方式二选一即可;日常运维建议统一 compose(第十节的命令都以 compose 为准)。

十、常用运维命令

以下命令均在部署目录(含 docker-compose.yml)内执行。

状态与资源占用:

docker compose ps
docker stats --no-stream --format '{{.Name}}  CPU={{.CPUPerc}}  MEM={{.MemUsage}}' dayglance-5.9.0-web

实测回显:

dayglance-5.9.0-web  CPU=0.00%  MEM=42.83MiB / 31.3GiB

(空载即约 43 MB 内存,CPU 归零——单用户场景资源占用可忽略。)

日志:

docker compose logs -f dayglance

(-f 跟随输出,Ctrl+C 退出;访问日志每行含来源 IP、方法、路径、状态码与字节数。)

升级到新版本(latest 标签形态):

docker compose pull
docker compose up -d

实测回显(已是最新时的 pull):

 Image ghcr.io/krelltunez/dayglance:latest Pulling
 Image ghcr.io/krelltunez/dayglance:latest Pulled

实测回显(镜像无变化时的 up -d):

 Container dayglance-5.9.0-web Running

镜像确有更新时,up -d 会重建容器(中断约 5 秒);数据在浏览器,无迁移负担。升级后若页面仍旧,浏览器强制刷新清掉 PWA 缓存(见十一、Q1)。升级前建议看一眼 Releases 页变更说明。

重启与停止:

docker compose restart dayglance   # 重启服务
docker compose stop                # 停止(保留容器)
docker compose down                # 删除容器与网络(数据在浏览器,不丢失)

十一、常见问题(FAQ)

Q1:升级后页面还是旧版本? PWA 的 Service Worker 缓存激进。浏览器强制刷新(Ctrl+Shift+R / Cmd+Shift+R)即可;官方自托管文档明确该排障项(2026-10-22 查询)。

Q2:容器意外重启怎么办? docker compose logs -f dayglance 查原因;该镜像极轻量,正常情况不会崩(官方口径同)。资源占用参考第十节实测(约 43 MB)。

Q3:可以直接暴露公网吗? 不可以裸暴露。内置代理是无鉴权中继(官方 README/源码注释双重声明),必须前置带认证的反向代理或开启 WEBDAV_PROXY_BLOCK_PRIVATE=1 并做网络层访问控制。推荐姿势:反向代理(Caddy/Nginx/Traefik)终结 HTTPS 并加认证,回源到 localhost:8131。

Q4:通知不弹? 浏览器通知要求 HTTPS 安全上下文,裸 HTTP 访问时通知不可用——这是浏览器平台约束,非故障。

Q5:同步上传报 413? 镜像内 Nginx 未配置 client_max_body_size,沿用默认 1 MB 请求体上限(实测 2 MB 请求体被拒 413,见第七节)。dayGLANCE 的同步内容是纯文本任务记录,正常远小于 1 MB;若确要传大文件,检查是否在前面自加了反向代理——Nginx 反代同样默认 1 MB,需要同步放开。

Q6:想把同步指向内网 NAS 却被 403 拒绝? 实例开启了 WEBDAV_PROXY_BLOCK_PRIVATE=1。去掉该变量(或设为 0)重启容器;仅在实例可能被不可信用户访问时才需要保持封锁。

Q7:多设备数据怎么保持一致? 各设备浏览器各自存数据,靠应用内配置同一个 WebDAV/Nextcloud 同步目标合并(任务级时间戳合并,非整文件覆盖)。服务器侧无共享状态,这正是第五节"无 volumes"的原因。

十二、参考链接