Docker 撰写:将输出记录到文件和标准输出
Docker Compose: Log output to both a file and stdout
我正在尝试将应用程序的输出同时记录到文件和标准输出。
仅将输出记录到标准输出并仅将输出记录到文件有效,但两者的组合无法按预期工作。
这里是 docker-compose.yml 的简化版本和一个启动脚本。
docker-compose.yml:
version: "3.8"
services:
web:
image: node:14
command: sh "/app/scripts/init-app.sh"
init: true
volumes:
- ./:/app
init-app.sh:
#!/usr/bin/env sh
# Exit script immediately if a command exits with a non-zero status.
set -e
# Install and configure app
[...]
# Start app
exec ./app
以上配置有效,但仅输出到标准输出。
修改 #1(初始化脚本的最后一行):
# Start app and log output to file
exec ./app >> "/app/log.txt" 2>&1
此配置也有效,将输出记录到文件,但不记录到标准输出。
修改 #2(初始化脚本的最后一行):
# Start app and log output to both a file and stdout
exec ./app 2>&1 | tee -a "/app/log.txt"
这会正确地输出到文件和标准输出,但会破坏容器的 start/stop 功能。
详情:
尽管使用 exec
调用,但当使用 tee
调用时,./app
不会 运行 作为 PID 1。
这是一个问题,因为当容器停止时(通过 CLI 或 GUI),docker 向 PID 为 1 的进程发送停止信号。./app
进程没有收到信号,因此 ./app
不停歇
如何在不破坏 start/stop 功能的情况下将输出记录到文件和标准输出?
// 编辑:固定修改#1
// Edit2:将“init: true”添加到 docker-compose.yml
您能否利用 docker 的 logging
capabilties-compose 来打印标准输出和日志文件?
Only the json-file and journald drivers make the logs available directly from docker-compose up and docker-compose logs. Using any other driver does not print any logs
我听说过一个最佳实践:
- 日志将被视为流。
- 应用程序本身不应管理日志记录(重定向、存储等),只能写入数据。
如果我应用它,docker 应该是唯一负责管理此流的人。
如果您接受这个原则,您可以只使用
启动脚本
exec ./app
您可以通过 运行
启动您的应用
docker-compose up web
需要时可以使用 control-c。
您可以在另一个终端访问日志并将它们重定向到一个文件
docker-compose logs -f web > web.log
我没有看到用例,但是如果您想同时启动和记录到标准输出并一直记录到文件,那么
# run and detach
docker-compose up -d web
# save logs to a file in the background
docker-compose logs -f web > web.log 2>&1 &
# reattach to the container to be able to do control-c
# it will not rerun the container, just reattach
docker-compose up web
我正在尝试将应用程序的输出同时记录到文件和标准输出。 仅将输出记录到标准输出并仅将输出记录到文件有效,但两者的组合无法按预期工作。
这里是 docker-compose.yml 的简化版本和一个启动脚本。
docker-compose.yml:
version: "3.8"
services:
web:
image: node:14
command: sh "/app/scripts/init-app.sh"
init: true
volumes:
- ./:/app
init-app.sh:
#!/usr/bin/env sh
# Exit script immediately if a command exits with a non-zero status.
set -e
# Install and configure app
[...]
# Start app
exec ./app
以上配置有效,但仅输出到标准输出。
修改 #1(初始化脚本的最后一行):
# Start app and log output to file
exec ./app >> "/app/log.txt" 2>&1
此配置也有效,将输出记录到文件,但不记录到标准输出。
修改 #2(初始化脚本的最后一行):
# Start app and log output to both a file and stdout
exec ./app 2>&1 | tee -a "/app/log.txt"
这会正确地输出到文件和标准输出,但会破坏容器的 start/stop 功能。
详情:
尽管使用 exec
调用,但当使用 tee
调用时,./app
不会 运行 作为 PID 1。
这是一个问题,因为当容器停止时(通过 CLI 或 GUI),docker 向 PID 为 1 的进程发送停止信号。./app
进程没有收到信号,因此 ./app
不停歇
如何在不破坏 start/stop 功能的情况下将输出记录到文件和标准输出?
// 编辑:固定修改#1
// Edit2:将“init: true”添加到 docker-compose.yml
您能否利用 docker 的 logging
capabilties-compose 来打印标准输出和日志文件?
Only the json-file and journald drivers make the logs available directly from docker-compose up and docker-compose logs. Using any other driver does not print any logs
我听说过一个最佳实践:
- 日志将被视为流。
- 应用程序本身不应管理日志记录(重定向、存储等),只能写入数据。
如果我应用它,docker 应该是唯一负责管理此流的人。
如果您接受这个原则,您可以只使用
启动脚本exec ./app
您可以通过 运行
启动您的应用docker-compose up web
需要时可以使用 control-c。
您可以在另一个终端访问日志并将它们重定向到一个文件
docker-compose logs -f web > web.log
我没有看到用例,但是如果您想同时启动和记录到标准输出并一直记录到文件,那么
# run and detach
docker-compose up -d web
# save logs to a file in the background
docker-compose logs -f web > web.log 2>&1 &
# reattach to the container to be able to do control-c
# it will not rerun the container, just reattach
docker-compose up web