在 ENTRYPOINT 中将流程通过管道传递给消费者有多糟糕?

How bad is it to pipe process to consumer in ENTRYPOINT?

在 Dockerfile 中使用这样的东西会有多糟糕:

ENTRYPOINT node . | tee >(send_logs_to_elastic_search)

大多数日志记录解决方案都需要一些非常讨厌的配置。以上将是我们以编程方式捕获日志并编写我们自己的胶水代码的一种方式。

上述解决方案的主要问题是 CMD 参数不会附加到 node 进程?我假设他们会改为附加到 tee 进程?像这样:

docker run foo --arg1 --arg2

我假设那看起来像:

node . | tee >(send_logs_to_elastic_search) --arg1 --arg2

有人知道吗?

另一个潜在的问题是您的容器的可配置性较低,它 "hardcoded" 将日志发送到 send_logs_to_elastic_search 进程。

你运行你的容器怎么样?

通常您可以将 filebeats 或其他东西直接连接到 /var/lib/docker/containers/*/*.json.log 并让主机发送所有容器的所有日志

这是 filebeats 的教程,非常好,因为他们使用另一个容器进行卷装载和日志提取

The Dockerfile documentation 表示如果您使用 ENTRYPOINT 的 shell 形式,则 CMD 将被完全忽略。如果不是,那么 CMD 基本上会按照您显示的方式附加。

如果这只是关于日志记录,我建议 setting up a Docker logging driver over trying to configure logging inside the container. This simplifies your image setup (it only needs the application and not every possible log target). Both logstash and fluentd 是仅用于移动日志消息的流行工具。

如果您正在查看更复杂的脚本,我几乎总是将其写入独立的 shell 脚本,而不是尝试将其直接写入 Dockerfile。

...
COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["node", "."]

入口点脚本将接收命令部分作为命令行参数。通常它会以 exec "$@" 结束,只是 运行 该命令。如果您愿意让 shell 包装器成为主容器进程,您可以将命令的输出通过管道传输到某处

#!/bin/sh
"$@" | send_logs_to_elasticsearch