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