bigywater.tech
Docker · 72

日志驱动:local、syslog 与 none 的差别

想把容器日志发到别的地方,日志驱动怎么选、发出去的是什么格式、发不出去会怎样?这篇用一个监听在虚拟机里的 UDP 接收端,看 gelf 和 syslog 实际发出的包,并验证 docker logs 在远程驱动下还能不能用。

2 个 UDP 包
gelf / syslog 驱动下,两行输出(stdout 与 stderr 各一行)在接收端各收到的包数
docker logs 仍可读
日志发往 gelf 或 syslog 时,docker logs 依然读到两行
125
gelf-address 指向没人监听的 TCP 端口时 docker run 的退出码

驱动列表

实测 · 本机执行输出
  docker info 的 Plugins.Log = [awslogs fluentd gcplogs gelf journald json-file local splunk syslog]

这个 Docker 内置了九种驱动,none 则完全不保留日志(docker logs 报 does not support reading)。

发出去的是什么

实测 · 本机执行输出
  docker logs 退出码 1;Error response from daemon: configured logging driver does not support reading

GELF 是每行一个 JSON 包(version、host、short_message、level、_container_id、_container_name…),stderr 的 level 是 3、stdout 是 6;syslog 用 rfc5424 格式,stdout 的优先级是 <30>、stderr 是 <27>,tag 出现在 APP-NAME 位置。接收端是我自己写的 Python UDP 监听,不是真正的 Graylog 或 syslog 服务。

docker logs 还能用

实测 · 本机执行输出
  --log-driver gelf:docker run 退出码 0
    接收端:共收到 2 个 UDP 包
    PKT {"version":"1.1","host":"docker-desktop","short_message":"hello-gelf","timestamp":1791639388.285,"level":6,"_command":"sh -c echo hello-gelf; echo err-gelf \u003e\u00262; sleep 20","_container_id":"5595be09bd49c0ce0e0e25dbee32e037f035afb140b62cfca788513a463d0f44","_container_name":"bwlab-c67-gelf","_created":"2026-10-10T13:3
    PKT {"version":"1.1","host":"docker-desktop","short_message":"err-gelf","timestamp":1791639388.286,"level":3,"_command":"sh -c echo hello-gelf; echo err-gelf \u003e\u00262; sleep 20","_container_id":"5595be09bd49c0ce0e0e25dbee32e037f035afb140b62cfca788513a463d0f44","_container_name":"bwlab-c67-gelf","_created":"2026-10-10T13:36:
    docker logs bwlab-c67-gelf:退出码 0;hello-gelf ⏎ err-gelf
  --log-driver syslog:docker run 退出码 0
    接收端:共收到 2 个 UDP 包
    PKT <27>1 2026-10-10T13:36:36Z docker-desktop c67-demo 283 c67-demo - err-syslog ⏎
    PKT <30>1 2026-10-10T13:36:36Z docker-desktop c67-demo 283 c67-demo - hello-syslog ⏎
    docker logs bwlab-c67-syslog:退出码 0;hello-syslog ⏎ err-syslog

日志发往 gelf 或 syslog 之后,docker logs 依然读到本地缓存的内容,说明 docker 在把日志发出去的同时也在本地保留了一份。缓存多大、保留多久,我没有测。

目标不可达

实测 · 本机执行输出
  gelf-address=tcp://127.0.0.1:1(没人监听):docker run 退出码 125;docker: Error response from daemon: failed to create task for container: failed to initialize logging driver: gelf: cannot connect to GELF endpoint: 127.0.0.1:1 dial tcp 127.0.0.1:1: connect: connecti
  gelf 用 UDP 发往没人监听的端口:docker run 退出码 0(UDP 不需要对方在线)

TCP 目标连不上,容器直接创建失败(125);UDP 因为不需要对方在线,容器能正常启动,但日志可能静默丢失。选驱动时要考虑这两种失败方式。

分步演示

日志驱动
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。接收端是 --network host 的 python:3.12-alpine 容器(即虚拟机的 127.0.0.1),监听 UDP 并打印每个包;gelf 与 syslog 的参数分别是 gelf-address=udp://… 与 syslog-address=udp://… ;每个驱动运行一次;实验后已删除容器和镜像
    • 没有验证:fluentd、awslogs、splunk、journald、gcplogs 驱动、gelf 的压缩选项、syslog 的 TCP / TLS、网络恢复后丢失日志的补发、非阻塞模式 mode=non-blocking 与 max-buffer-size 的效果
    京ICP备2026067502号-1京公网安备11010502063487号