Docker应用日志转stdout后如何区分不同来源日志?
给Docker应用的stdout日志添加来源标识的解决方案
我之前处理Docker容器日志时遇到过完全一样的需求——把所有日志统一打到stdout后,混在一起根本分不清哪条属于哪个服务。下面几个亲测有效的方案,你可以根据场景选择:
1. 直接修改Nginx日志格式,添加[nginx]前缀
Nginx本身支持自定义日志格式,这是给Nginx日志加前缀最省事的办法,不需要额外工具。修改你的Nginx配置:
# 定义带来源标识的日志格式 log_format main '[nginx] $remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 指定用这个格式输出到stdout access_log /dev/fd/1 main; error_log /dev/fd/1 error;
这样Nginx的访问日志和错误日志每一行都会自动带上[nginx]前缀,完美区分。
2. 用Supervisor的stdout_capture_cmd给进程日志加前缀
对于Supervisor管理的其他进程(比如你的app服务),可以利用stdout_capture_cmd参数,通过sed给每一行日志加前缀。修改你的Supervisor配置:
[program:app] command=/bin/bash -c "exec npm run start-generic" directory=/app01 # 用sed在每一行开头插入[app] 前缀 stdout_capture_cmd=/usr/bin/sed 's/^/[app] /' stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 autostart=true autorestart=true startretries=0 stopasgroup=true [program:nginx] command=/usr/sbin/nginx -g "daemon off;" # 如果没改Nginx的log_format,也可以用这个方式加前缀 stdout_capture_cmd=/usr/bin/sed 's/^/[nginx] /' stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0
注意:要确保容器里安装了sed工具。如果是Debian/Ubuntu镜像,Dockerfile里加RUN apt-get update && apt-get install -y sed;如果是Alpine镜像,用RUN apk add --no-cache sed。
3. 自定义shell脚本包装启动命令(更灵活的方案)
如果需要更复杂的日志处理(比如过滤特定日志、处理多行日志),可以写个简单的shell脚本实现前缀添加。比如创建wrap-log.sh:
#!/bin/bash # 第一个参数是日志来源标识,比如app、nginx PREFIX="[$1]" # 移除第一个参数,剩下的是要执行的命令 shift # 执行命令并给每行输出加前缀 "$@" | while read -r line; do echo "$PREFIX $line" done
把脚本放到容器里(比如/app01/wrap-log.sh),给它加执行权限:chmod +x /app01/wrap-log.sh。
然后修改Supervisor的command配置:
[program:app] command=/bin/bash -c "exec /app01/wrap-log.sh app npm run start-generic" directory=/app01 stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 autostart=true autorestart=true startretries=0 stopasgroup=true
这个方案的好处是可以随时修改脚本,实现更复杂的逻辑,比如只给错误日志加特殊标识,或者处理换行的日志内容。
内容的提问来源于stack exchange,提问作者Ashutosh Singh
相关产品推荐
相关产品推荐

