网站请求经过代理、应用和数据库,排障时却常常只开着应用的一份日志。应用写连接失败,代理写上游超时,数据库可能早几秒就已重启。来回执行 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 指向的是新宿主机,旧配置中的名称不会让你继续看到旧机器的日志。
部署完成以后,需要排障时再打开这个入口。出现错误时选对容器、找到第一条异常、把关联记录和处理过程留到故障笔记里,下一次就能沿着已有证据继续查。