在 docker 容器内安装目录

问题描述 投票:0回答:1

我正在尝试为我的 Docker 容器构建一些日志可观察性。我需要做的是能够启动任意数量的容器并将它们的日志目录挂载到主机系统,以便 Datadog 代理可以保留主机上所有容器的日志。目前我正在使用 docker compose 文件和

--scale
命令

来完成此操作
docker compose -p application -f application-compose.yaml up -d --scale service=3

因为我们使用 DataDog,由于 DataDog 的定价结构,我无法构建代理并将其部署到容器中。这将导致大量主机被检测到,并且对我们来说成本高昂。我也无法选择使用另一个日志聚合器。

如果有任何后果,我会在主机和容器上运行 Alpine Linux。

这就是我找到的解决方案。在入口点脚本运行时,我将

/var/log
目录安装到
/host_logs
目录。我使用 docker 容器的主机名执行此操作,以便能够使用以下命令将日志与其他容器分开:

mount --bind "/host_logs/${HOSTNAME}" /var/log

然后,我在 docker-compose 文件中使用以下配置将此目录安装到主机上:

volumes:
  - "${HOST_LOG_PATH:-/var/log/application/}:/host_logs"

这允许我在 .env 文件中指定 HOST_LOG_PATH,或者将卷直接安装到容器内运行的应用程序的定义位置下的主机。

这会导致主机系统看到应用程序日志目录安装如下:

mount structure

这一切都很好地解决了一个问题,即此绑定挂载需要容器为容器启用

SYS_ADMIN
功能。我的理解是,这有潜在的危险,因为它可能允许容器内运行的任何代码将容器转义到主机上。

因为我无法访问可以编写脚本的任何变量,因此无法在 docker-compose 文件或 .env 文件中随机化,所以我无法找到一种方法来有效地隔离每个容器的主机上的日志。我已经考虑过稍微修改容器的默认安全配置文件并仅允许附加安装命令,但这似乎也有潜在危险,并且仍然需要授予附加功能,因为仅在安全配置文件中授予安装命令似乎并不可行就足够了。我也不想在这里执行任何类型的 bash 脚本来动态设置环境变量,然后运行 compose 命令,因为这种复杂性很快就会失控。

在使用绑定挂载之前,我尝试简单地将

/var/log
目录符号链接到另一个目录,以便我可以在不使用绑定挂载的情况下传输所有日志。尽管如此,我仍然需要使用硬链接以确保文件内容正确映射到新位置。我无法对容器中的目录使用硬挂载,因为符号链接硬链接仅适用于文件而不适用于目录。

我可以将独立文件符号链接到新位置,但随后我就无法捕获进入

/var/log
目录的任何新内容,而无需在入口点脚本中指定它。这也不起作用,因为我需要能够动态抓取容器上
/var/log
目录中的所有内容并将其传递给主机,以确保容器内没有其他内容在我们不知情的情况下开始运行。

所以我的要求如下:

  1. 确保主机上的每个容器的所有日志都以某种可识别的方式隔离。
  2. 尽可能安全,不要向容器添加额外的有问题的功能。
  3. 确保
    /var/log
    中容器内的所有物品在出现时都被收集起来。
  4. 需要尽可能少地修改入口点、Dockerfile 和 docker-compose 文件。
  5. 我想避免主机上的另一个容器纯粹是为了从其他容器收集日志。

是否有一种合理的方法可以在不使用

SYS_ADMIN
功能的情况下允许此功能?有没有更好的方法来进行日志聚合?或者这只是从 docker 容器中运输日志的复杂现实?

docker logging docker-compose alpine-linux observability
1个回答
0
投票

这就是我使用 php 在 docker 容器内挂载目录的方法。

docker run -d -v /var/log/application/:/host_logs k3_s3:latest

© www.soinside.com 2019 - 2024. All rights reserved.