【问题标题】:How does Java application know it is running within a Docker container [duplicate]Java应用程序如何知道它正在Docker容器中运行[重复]
【发布时间】:2019-03-15 04:04:37
【问题描述】:

我为我的应用程序编写了一个 DockerFile,主要是为了允许它在 NAS 机器中运行(通过 Docker)。 Web 界面允许用户遍历文件系统树来查找音乐文件,但是当使用 Docker 时,文件系统树是无关紧要的,除了 /Music 卷,它是用户在 NAS 上的实际音乐文件夹的挂载点。

所以我只想显示 /Music 文件夹而不是整个文件系统树,为此应用程序需要知道它实际上是在 Docker 中运行,而不是在实际的本地 Linux 操作系统中运行。

应用程序知道它的正确方法是在docker中,应用程序是用Java编写的。

【问题讨论】:

  • 这不是重复的,因为这个答案专门询问如何检查 Java,其他答案没有解决这个问题

标签: java docker dockerfile


【解决方案1】:

解决方案

简单地通过/proc/1/cgroup检查初始化进程的控制组。

  • 如果正常启动,所有层次结构的/
  • 如果它是从 docker 容器启动的,它们具有/docker/<container_id> 值。

在 docker 内部运行时,/proc/1/cgroup 的值类似于:

11:perf_event:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
10:memory:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
9:cpuset:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
8:net_cls,net_prio:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
7:pids:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
6:cpu,cpuacct:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
5:blkio:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
4:freezer:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
3:hugetlb:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
2:devices:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
1:name=systemd:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249

注意:@JanisKirsteins 告诉我,如果您在 amazon ec2 中运行您的应用程序,您可能希望将条件更改为 line.contains("/ecs")。因为在/proc/1/cgroups 你会发现类似于:/ecs/<uuid>/<uuid> 的模式


在 Java 中

public static Boolean isRunningInsideDocker() {

        try (Stream < String > stream =
            Files.lines(Paths.get("/proc/1/cgroup"))) {
            return stream.anyMatch(line -> line.contains("/docker"));
        } catch (IOException e) {
            return false;
        }
    }

实时代码检查


更多信息

【讨论】:

  • 谢谢,这似乎是正确的答案。
  • 值得注意的是需要检查文件是否存在,即在没有此文件的 Windows 上
  • 亲爱的@PaulTaylor,我更新了我的答案,当文件不存在时,它会引发异常,您可以从那里返回 false ,我提供了 2 个用于实时检查代码的链接:其中一个在 docker 内部运行,另一个没有。
  • 感谢您为此提供的所有帮助。
  • 这将错过例如在 ECS 中运行的应用程序(将改为 /ecs//
【解决方案2】:

运行容器时添加volume 选项。

docker run -v /Music:/Music <image-name>

: 的右侧是应用程序查找目录的位置。我以为是 /Music。

如果您真的想检查您的应用程序是否在 docker 中运行,您可以检查文件“/.dockerenv”是否存在。根据您的问题,您应该知道的一件事是,当您的应用程序在 docker 内运行时,除非您通过卷授予访问权限,否则它无法访问主机的文件系统。所以,如果你真正的 linux 机器有一个目录 /Music,你的应用程序就无法访问它。您通过--volume 提供访问权限。当您在 docker 中运行应用程序时,您可以将其视为在其他虚拟机或机器中运行,以实现所有实际目的。这就是 Docker 本身的主要目的:提供隔离。

【讨论】:

  • 是的,我可以这样做,但这不是问题所在。我的应用程序如何知道它在 Docker 中运行,它可以检查 /Music 文件夹是否存在,但真正的 linix 机器也可能有 /Music 文件夹,我在问是否有标准方法来识别是否在 Docker 中运行,即 uname 是否告诉你这一点。
  • 更新了答案以回答您的问题。
  • 显然根据链接的答案 /.dockenv 是不可靠的解决方案。你对 Docker 的主要用途是错误的,如果大多数 Docker 应用程序无法访问真实的文件系统,它们将毫无用处。
猜你喜欢
  • 2018-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-05
  • 1970-01-01
  • 1970-01-01
  • 2016-08-05
相关资源
最近更新 更多