在 VPS 上部署 Dozzle:三个容器一起报错时,把日志放到同一屏里看

部署 Dozzle 查看多容器日志,配置私人登录、时间线排查与日志轮转,核对 Docker socket 权限边界。

·8 mindevops

网站请求经过代理、应用和数据库,排障时却常常只开着应用的一份日志。应用写连接失败,代理写上游超时,数据库可能早几秒就已重启。来回执行 docker logs,很容易错过发生顺序。Dozzle 可以在浏览器里查看多个容器的日志,配合时间和搜索定位问题。

这里部署一个只给维护者使用的入口,启用登录,保持容器操作与 Shell 功能关闭。Dozzle 要访问 Docker API,不能把它当普通静态网页开放。即便 socket 挂载写了 :ro,也不会把 API 限制成只读;能打开这个管理入口的人和软件,都需要处在明确的信任范围内。

先确认应用有没有把日志交给 Docker

Dozzle 主要读取 Docker 捕获的 stdout 和 stderr,也就是 docker logs 能看到的内容。应用把错误写进容器内部某个文件,却没有输出到标准流,Dozzle 不会自动找出那个文件。部署之前先选一个目标容器,执行下面的命令,替换容器名。

docker logs --timestamps --tail=80 app-container

如果这里没有需要的内容,先检查应用日志配置。能修改应用时,优先让它输出到标准流;必须跟踪文件时,可以按官方文档安排只读挂载的日志 sidecar,但要确定实际目录和轮转行为。不要为了查看一份日志把所有宿主机目录都挂进浏览器工具。

实时查看与长期归档也是两件事。Docker 清理了旧日志,或容器删除重建以后,历史是否还存在取决于原有日志驱动和保留方式。Dozzle 页面里的搜索不能代替集中日志存储。需要保留几个月的审计记录,应另行规划存储、脱敏和访问控制。

先生成用户,再启动网页

服务器已安装 Docker Engine 与 Compose 插件,当前用户具备 Docker 权限。Caddy 运行在宿主机,域名 logs.example.com 指向 VPS。先建立数据目录,使用 Dozzle 自带命令生成用户文件。

mkdir -p /opt/dozzle/data
cd /opt/dozzle
umask 077
docker run -it --rm amir20/dozzle:latest generate admin --name "Server Admin" > data/users.yml

省略 --password 后工具会交互询问密码,避免把明文写进 Shell 历史。命令输出保存到 users.yml,其中是应用使用的用户配置。检查文件生成成功,不要把包含凭据的内容贴到公开讨论区。生成与正式运行应使用相同的镜像版本。

保存下列内容为 compose.yaml。数据目录既保存用户文件,也保存应用设置。宿主机端口限制在回环地址,外部只能经代理或私人网络进入。

services:
  dozzle:
    image: amir20/dozzle:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:8088:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data:/data
    environment:
      DOZZLE_AUTH_PROVIDER: simple
      DOZZLE_ENABLE_ACTIONS: "false"
      DOZZLE_ENABLE_SHELL: "false"
      DOZZLE_HOSTNAME: main-vps

这里的 :ro 只限制挂载文件的写入,Docker API 仍可经 socket 访问。关闭页面操作按钮也不是宿主机权限隔离。确实需要限制 API 时,应按官方说明设置 socket proxy,只允许所需接口,并验证实际功能;这份基础配置不声称具备那种限制。

首次拉取稳定镜像后,记录摘要并固定运行版本。不要同时自动更新日志工具与一堆被监控应用,出了问题会很难判断哪项变更影响了日志。

docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=80 dozzle
curl -I http://127.0.0.1:8088/

如果没有容器列表,检查 socket 挂载和访问权限。不要把给所有人修改 socket 的权限作为解决办法。应用看不到 Docker 时,页面依然可能加载,网页正常与 Docker 连接正常需要分别验证。

管理入口保持简单而明确

先通过 SSH 转发访问本机 18088 端口,验证登录成功。再开一个未登录窗口,确认不能直接查看容器日志。

ssh -N -L 18088:127.0.0.1:8088 [email protected]

如果只给自己使用,保留这种入口或放进 VPN 就够了。需要正式域名时,宿主机 Caddy 添加下面的站点段,验证配置后重载,并保持 Dozzle 自身登录启用。

logs.example.com {
    reverse_proxy 127.0.0.1:8088
}

代理在容器里时,使用共享网络上的服务地址。不要为了代理连通把 8088 改成对所有地址开放。以后接入其他认证系统时,按对应模式重新检查可信头和绕过路径,不能只设置一个用户头就认为登录已经可靠。

多人使用时,分别建立用户,按当前版本支持的角色与过滤条件安排可见容器。默认看得到哪些服务,要用普通用户真实登录确认。日志中可能包含邮箱、请求参数甚至配置错误打印出的令牌,分享截图前先脱敏。

用一件小故障练习找时间线

选择代理和应用两个容器,并排查看日志。先请求一个由自己管理的测试路径,确认两边的时间戳和请求记录对应。若应用有请求 ID,就用它搜索关联记录;没有时,可以结合路径、时间和状态码,但要保留无法唯一对应的限制。

接下来找一段过去的启动日志,观察应用是否先等待数据库,再开始监听。启动完成的消息之后出现数据库连接错误,与进程从未启动成功不是同一类问题。记录最早出现的有效错误,不要只抄最后一段重复堆栈。

搜索关键词时先用具体的异常名称或接口路径,再缩小时间范围。“error”可能命中大量无关记录,也会漏掉用其他级别打印的问题。日志滚动得很快时暂停跟随,读完上下文再恢复,避免刚找到的一行又被新内容挤走。

容器名称尽量能表达用途。如果列表里都是随机名字,排障时很容易点错环境。名称或标签的显示配置只帮助识别,仍需确认实际容器、镜像与部署目录,不把页面中的友好名称当作生产归属的唯一证据。

有日志,也不一定能说明问题

代理写超时,可能是应用慢、网络断、进程卡住或下游依赖异常。Dozzle 能把信息放在一起,但不会自动证明根因。结合容器重启次数、CPU、内存和应用健康检查判断,保留尚未排除的原因。

时间线对不上时检查宿主机时间、应用日志时区和浏览器显示。程序正文中的时间字符串与 Docker 附加的时间戳可能不同。跨机器排障尤其要明确时区,不能看到两个相似时间就直接认定同一事件。

某个容器长时间没有新日志,先在服务器执行一次 docker logs 对照。只有网页不更新,再检查连接与代理;两边都没有,则检查应用是否输出或任务是否实际触发。提高 Dozzle debug 级别只用于定位工具自身问题,不能让目标应用凭空产生日志。

日志轮转由原有部署负责

先查看当前日志驱动及占用,再安排轮转。对于使用兼容日志驱动的 Compose 服务,可以在它自己的配置里设置容量和份数,修改后重建目标容器。下面是示例片段,不是让你替换整份业务部署。

logging:
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"

保留多少应按故障追溯需要和磁盘容量决定。很小的限额可能在一次高流量错误中迅速覆盖关键记录;没有限额则可能占满磁盘。需要长期存档时把日志送到专门系统,不靠加大本机文件无限保留。

不要为了清理空间删除运行中的日志文件或手动修改 Docker 内部目录。使用日志驱动和部署管理支持的方式,先保留故障样本,避免清理完才发现正要追查的时间段已经丢失。

备份登录配置,不把工具数据当作全量日志

备份 data 与 Compose,保存确切镜像版本。Dozzle 的设置数据不等于全部被监控容器的日志,原有业务日志和归档仍按各自的方案备份。

cd /opt/dozzle
mkdir -p /opt/backups
docker compose stop dozzle
tar -czf "/opt/backups/dozzle-$(date +%F-%H%M).tgz" compose.yaml data
docker compose start dozzle

恢复时先在私人入口启动,检查用户、角色与可见范围,暂时不要连接不打算开放的宿主机。迁移到新机器以后,socket 指向的是新宿主机,旧配置中的名称不会让你继续看到旧机器的日志。

部署完成以后,需要排障时再打开这个入口。出现错误时选对容器、找到第一条异常、把关联记录和处理过程留到故障笔记里,下一次就能沿着已有证据继续查。