如何确定某个进程是否在 lxc/Docker 内部运行?
- 2024-10-18 09:00:00
- admin 原创
- 64
问题描述:
有什么方法可以确定进程(脚本)是否在 lxc 容器(〜Docker 运行时)内运行?我知道有些程序能够检测它们是否在虚拟机内运行,lxc/docker 是否有类似的东西?
解决方案 1:
.dockerenv
Docker在容器内的目录树根目录创建一个文件。执行以下命令可以看到ls -la /.dockerenv
它是在容器启动时创建的。
您可以运行此脚本来验证:
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
更多:
Ubuntu 实际上有一个 bash 脚本:/bin/running-in-container
它可以返回它被调用的容器类型。可能会有帮助。不过不知道其他主要发行版的情况。
解决方案 2:
最可靠的方法是检查/proc/1/cgroup
。它将告诉您 init 进程的控制组,当您不在容器中时,它将适用/
于所有层次结构。当您在容器内时,您将看到锚点的名称。对于 LXC/Docker 容器,它将分别类似于/lxc/<containerid>
或/docker/<containerid>
。
解决方案 3:
在新的 ubuntu 16.04 系统上,新的 systemd 和 lxc 2.0
sudo grep -qa container=lxc /proc/1/environ
解决方案 4:
在 Bash 脚本中检查 docker/lxc 的简洁方法是:
#!/bin/bash
if grep -sq 'docker|lxc' /proc/1/cgroup; then
echo "I am running on Docker."
fi
解决方案 5:
方便的 Python 函数来检查是否在 Docker 中运行:
def in_docker():
""" Returns: True if running in a Docker container, else False """
with open('/proc/1/cgroup', 'rt') as ifh:
return 'docker' in ifh.read()
解决方案 6:
截至 2022 年,使用 lxd v4.0+,到目前为止,没有任何答案适用于 docker 和 lxc。
文件
.dockerenv
不适用于非docker容器。检查所有层次结构
/proc/1/cgroup
是否都/
有效也许可行。但是,非容器上的某些层次结构是有效的/init.scope
(Ubuntu 20.04 cgroup 0 和 1)。因此也不完全可靠。检查 lxc 是否
container=lxc
工作/proc/1/environ
,但 docker 不工作。此外,它需要 root 权限。
到目前为止我发现的唯一可以在 CentOS 和 Ubuntu 上使用 lxc(4.0)容器和 Docker 可靠运行并且不需要 root 权限的方法是检查 PID 2。
在所有主机系统上,PID 2 是kthreadd
:
$ ps -p 2
PID TTY TIME CMD
2 ? 00:00:00 kthreadd
在容器中,此 PID 要么不存在,要么不是 kthreadd。docker 和 lxc 都显示:
root@85396f8bce58:/# ps -p 2
PID TTY TIME CMD
root@85396f8bce58:/#
最好的方法似乎是检查/proc/2/status
:
$ head -n1 /proc/2/status
Name: kthreadd
因此这样的事情似乎有效:
if [ -n "$(grep 'kthreadd' /proc/2/status 2>/dev/null)" ]; then
echo "Not in container"
else
echo "In container";
fi
解决方案 7:
我们使用 proc 的 sched (/proc/$PID/sched) 来提取进程的 PID。容器内的进程 PID 将与主机(非容器系统)上的进程 PID 不同。
例如,容器上的 /proc/1/sched 的输出将返回:
root@33044d65037c:~# cat /proc/1/sched | head -n 1
bash (5276, #threads: 1)
在非容器主机上:
$ cat /proc/1/sched | head -n 1
init (1, #threads: 1)
这有助于区分您是否在容器中。
解决方案 8:
最简单的方法是检查环境。如果你有变量container=lxc
,则说明你位于容器内。
否则,如果您是root用户,您可以尝试执行mknod
或mount
操作,如果失败,则您很可能处于具有丢失功能的容器中。
解决方案 9:
这是一个老问题,但确实是一个好问题。:)
我编写了一些自动化脚本,我们在裸机、虚拟机和 Docker 容器中运行这些脚本,并根据脚本在哪个平台上执行进行逻辑分支。就我而言,我有权创建容器和 Docker 映像,因此只有当您控制整个堆栈时,此解决方案才会起作用:
Dockerfile 片段:
FROM ubuntu:18.04
ENV PLATFORM="docker"
RUN apt update; \n...
$PLATFORM
然后,脚本就可以检查每个平台上所需结果的值:
#!/bin/bash
# Check for executor specification in environment
case $PLATFORM in
docker)
# If running in Docker, do this stuff
echo "Running containerized, proceeding..."
;;
virtual)
# If running in a VM, do different stuff
echo "Running on a VM, loading VM stuff..."
modprobe some-kernel-module
;;
*)
echo "Unknown executor specified! Exiting..."
exit 1
;;
esac
为了保持简洁,我在上面的代码中省略了裸机。
解决方案 10:
在 Python 中检查上述所有解决方案:
import os
def in_container():
proc_1 = r'/proc/1/sched'
if os.path.exists(proc_1):
with open(proc_1, 'r') as fp:
out = fp.read()
else:
out = ''
checks = [
'docker' in out,
'/lxc/' in out,
out.split(' ')[0] not in ('systemd', 'init',),
os.path.exists('./dockerenv'),
os.path.exists('/.dockerenv'),
os.path.exists('/.dockerinit'),
os.getenv('container') is not None
]
return any(checks)
if __name__ == '__main__':
print(in_container())
概念证明:
$ docker run --rm -it --mount type=bind,source=${PWD}/incontainer.py,target=/tmp/script.py python:3 python /tmp/script.py
True
解决方案 11:
这个 SO Q&A:“查明操作系统是否在虚拟环境中运行”;虽然与 OP 的问题不一样,但它确实回答了查找您所在容器的常见情况(如果有的话)。
特别是,安装并阅读这个似乎运行良好的 bash 脚本的代码:
virt-什么:
sudo apt install virt-what
解决方案 12:
在 docker 容器中,条目/proc/self/cgroup
被挂载到主机上的 cgroups。
例如在容器中
# awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/docker/22bd0c154fb4e0d1b6c748faf1f1a12116acc21ce287618a115ad2bea41256b3
而在主机上
$ awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/
使用外壳中的某些东西进行低调测试
is_running_in_container() {
awk -F: '/cpuset/ && $3 ~ /^/$/ { c=1 } END{ exit c }' /proc/self/cgroup
}
if is_running_in_container; then
echo "Aye!! I'm in a container"
else
echo "Nay!! I'm not in a container"
fi
解决方案 13:
我的答案仅适用于Node.js 流程,但对于偶然发现该问题并寻找 Node.js 特定答案的某些访问者来说可能具有相关性。
我遇到了同样的问题,并且依靠这个原因,/proc/self/cgroup
我创建了一个npm 包,专门用于这个目的——检测 Node.js 进程是否在 Docker 容器内运行。
容器化的 npm 模块将在 Node.js 中为您提供帮助。它目前尚未在 Io.js 中测试,但可能也同样有效。
解决方案 14:
我已将 JJC 的答案翻译成 ruby
def in_docker
File.open('/proc/1/cgroup', 'rt') do |f|
contents = f.read
return contents =~ /docker/i || contents =~ /kubepod/i
end
rescue StandardError => e
p 'Local development'
p e
false
end
解决方案 15:
稍微偏离主题一点,您可以通过两种方式检查您是否在容器中:
`cat /proc/1/environ|tr "