Docker Compose如何实现日志同时输出到文件与stdout且不影响容器启停
解决方案
方案1:使用进程替换避免管道导致的PID1异常
这是改造成本最低的方案,无需调整Docker Compose配置,仅修改启动脚本即可:
- 首先确认容器镜像包含Bash,将
init-app.sh的首行shebang修改为:
#!/bin/bash
- 将原来的管道启动命令替换为进程替换写法:
# 启动应用,同时输出到stdout和日志文件,PID1仍为./app进程 exec ./app > >(tee -a /app/log.txt) 2>&1
原理说明
- 进程替换
>(tee ...)是Bash提供的特性,会在后台创建tee进程接收输出,不会引入管道子进程链 exec仍然会替换当前Shell进程为./app,保证./app是PID 1进程,可以正常接收Docker发送的停止信号- 你的Compose配置里已经开启了
init: true,会自动处理孤儿进程回收,无需额外调整
方案2:备选(无需修改启动脚本)
如果你不想调整应用启动逻辑,可以利用Docker自带的日志收集能力实现需求:
- 保持原来仅输出到stdout的启动配置
- 在Docker Compose中补充日志驱动和挂载配置即可:
version: "3.8" services: web: image: node:14 command: sh "/app/scripts/init-app.sh" init: true volumes: - ./:/app logging: driver: "json-file" options: max-size: "10m" max-file: "3"
该方案下日志会同时存在于Docker的默认日志存储路径(可通过docker logs命令查看)和你挂载的宿主机目录下,同样不会影响容器启停逻辑。
验证方法
容器启动后执行以下命令,确认PID 1为你的应用进程即可:
docker exec <你的容器名/ID> ps 1
内容的提问来源于stack exchange,提问作者squarebrackets
相关产品推荐
相关产品推荐

