Docker原生docker logs不捕获系统调用日志,仅收集stdout/stderr;需用strace、bpftrace/BCC或sysdig等内核级工具跟踪PID、cgroup或容器名实现syscall监控。
Docker 原生的 docker logs不捕获系统调用(syscall)日志,它只收集容器进程的标准输出(stdout)和标准错误(stderr)。系统调用属于内核层面行为,需借助外部工具实现监控。
要实时监控容器的系统调用日志,核心思路是:在容器运行时,对其中的主进程(或其子进程)进行 syscall 跟踪。常用且可靠的方法如下:
适用于调试、临时分析,无需修改容器镜像。
先获取容器内主进程 PID(宿主机视角):
docker inspect -f '{{.State.Pid}}' <容器名或ID>
输出如 12345,即该容器在宿主机上的 init 进程 PID。
使用 strace 实时跟踪该 PID 的所有系统调用:
sudo strace -p 12345 -e trace=all -s 256 -t
-e trace=all:捕获全部 syscall(可替换为 -e trace=open,read,write,connect 等缩小范围)-s 256:显示最多 256 字符的字符串参数(避免截断路径、URL 等)-t:打印时间戳(精确到秒)⚠️ 注意:需 root 权限;若容器使用 PID namespace 隔离(默认开启),strace 仍可工作,但无法跟踪已退出的子进程;频繁 syscall 可能带来性能开销。
基于 eBPF,低开销、高灵活性,支持按容器/进程过滤。
示例:监控某容器(如 nginx-app)内所有进程的 openat 和 connect 调用
sudo bpftrace -e 'kprobe:sys_openat, kprobe:sys_connect {if (cgroup.path == "/docker/<容器ID>") {printf("[%s] %s -> %sn", strftime("%H:%M:%S"), comm, probe);}}'
<容器ID> 需替换为 docker inspect -f '{{.Id}}' nginx-app 获取的完整 ID(前几位即可)cgroup.path 是识别容器的关键依据(Docker 默认将容器置于 /docker/xxx cgroup 下)更轻量的现成工具:bcc-tools 中的 opensnoop、execsnoop、tcplife 等可直接按容器过滤:
# 监控该容器发起的所有新连接sudo tcplife -C -i docker/<容器ID>
安装后一条命令即可按容器维度抓 syscall:
安装 sysdig(Ubuntu/Debian):
curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash
实时监控某容器的全部 syscall(带进程名、参数、返回值):
sudo sysdig -p "*%evt.time,%user.name,%proc.name,%evt.type,%evt.arg" "container.name=nginx-app" | head -n 50
过滤高频敏感调用(如 execve, mmap, socket):
sudo sysdig -c spy_syscalls container.name=nginx-app
docker logs 仅转发应用写入 stdout/stderr 的内容,比如 printf("hello") 或 log.Info()。open()、read()、clone()、kill() 等系统调用本身不会自动打日志——除非应用主动记录(如用 strace -o /tmp/log ... 启动并重定向),但这需要改造启动方式,且日志格式非结构化。不复杂但容易忽略:真正要监控 syscall,必须绕过 Docker 日志机制,直接与内核交互。选 strace 快速验证,选 bpftrace 或 sysdig 用于长期可观测场景。