Docker Compose:将输出记录到文件和标准输出

squ*_*ket 4 exec sh tee docker docker-compose

我正在尝试将应用程序的输出记录到文件和标准输出中。仅将输出记录到 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
Run Code Online (Sandbox Code Playgroud)

初始化应用程序.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
Run Code Online (Sandbox Code Playgroud)

上面的配置有效,但仅输出到标准输出。

修改#1(初始化脚本的最后一行):

# Start app and log output to file
exec ./app >> "/app/log.txt" 2>&1
Run Code Online (Sandbox Code Playgroud)

此配置也有效,将输出记录到文件,但不记录到标准输出。

修改#2(初始化脚本的最后一行):

# Start app and log output to both a file and stdout
exec ./app 2>&1 | tee -a "/app/log.txt"
Run Code Online (Sandbox Code Playgroud)

这可以正确输出到文件和标准输出,但它会破坏容器的启动/停止功能。

详细信息:尽管使用 调用exec,但./app在使用 调用时不会以 PID 1 运行tee。这是一个问题,因为当容器停止时(通过 CLI 或 GUI),docker 会向 PID 为 1 的进程发送停止信号。该./app进程不会收到该信号,因此./app不会停止。

如何在不破坏启动/停止功能的情况下将输出记录到文件和标准输出?

// 编辑:修复修改#1

// Edit2: 将“init: true”添加到 docker-compose.yml

Rap*_*OLO 6

我听说过一个最佳实践:

  • 日志将被视为流。
  • 应用程序本身不应管理日志记录(重定向、存储等),而应仅写入数据。

如果我应用这个,docker应该是唯一负责管理这个流的人。

如果您接受这个原则,您可以只使用启动脚本

exec ./app
Run Code Online (Sandbox Code Playgroud)

你可以通过运行来启动你的应用程序

docker-compose up web
Run Code Online (Sandbox Code Playgroud)

如果需要,可以使用 control-c。

您可以在另一个终端中访问日志并将其重定向到文件

docker-compose logs -f web > web.log
Run Code Online (Sandbox Code Playgroud)

我没有看到用例,但如果您想同时启动和记录到标准输出并始终记录到文件,那么

# 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
Run Code Online (Sandbox Code Playgroud)

  • 我找到了:可扩展应用程序的 12 条规则:https://12factor.net/logs (2认同)