有什么方法可以确定进程(脚本)是否在lxc容器(〜Docker运行时)中运行?我知道有些程序能够检测它们是否在虚拟机中运行,是否可以将类似的东西用于lxc / docker?
有什么方法可以确定进程(脚本)是否在lxc容器(〜Docker运行时)中运行?我知道有些程序能够检测它们是否在虚拟机中运行,是否可以将类似的东西用于lxc / docker?
Answers:
最可靠的方法是检查/proc/1/cgroup
。它将告诉您初始化过程的控制组,并且当您不在容器中时,它将/
用于所有层次结构。当您在容器内时,将看到锚点的名称。使用LXC / Docker容器,将分别类似于/lxc/<containerid>
或/docker/<containerid>
。
docker
而不是lxc
在这些路径中使用
/
所有cgroup都使用process 1 。我的Debian 9的系统上(systemd 232)只有三个十cgroup中的(3:cpuset
,4:perf_event
和7:freezer
)是在根; 其余的都在/init.scope
。也就是说,我认为搜索该文件:/docker/
可能是目前最可靠的启发式方法。
grep 'docker\|lxc' /proc/1/cgroup
在Docker 18.09上为我工作。
Docker .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
它实际上可以返回已被调用的容器的类型。可能会有帮助。虽然不了解其他主要发行版。
/bin/running-in-container
上由提供upstart
。随着向systemd的过渡,它可能会消失。我希望不会-听起来很有用!
我们使用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)
这有助于区分是否在容器中。
sh
不init
存在,但是两者中几乎都可以。
bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
最简单的方法是检查环境。如果您具有container=lxc
变量,则说明您位于容器中。
否则,如果您是root用户,则可以尝试执行mknod
或mount
操作,如果失败,则很可能是您的容器中的功能已被丢弃。
/proc/1/cgroup
您无法检测到。
docker run alpine env
没有给出看起来像该变量的任何东西
检查以上所有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('/.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
def is_non_docker(): return os.path.exists('/proc/1/cgroup')
按照这里公认的答案stackoverflow.com/questions/20010199/…–
cat
!好人:-D
Docker每天都在发展,因此我们无法确定它们是否会.dockerenv .dockerinit
在未来继续 发展。
在大多数Linux版本中,这init
是第一个启动的过程。但是对于容器来说,这是不正确的。
#!/bin/bash
if ps -p1|grep -q init;then
echo "non-docker"
else
echo "docker"
fi
init
,这在基于systemd
或launchd
基于系统的系统上是不正确的
init
),OpenRC,initng,runit。看这里。大多数现代的基于Linux的系统都将使用systemd
,有些则是较早的新贵...。所有现代的OS X系统都将使用launchd
这样的SO问答:“找出操作系统是否在虚拟环境中运行”;尽管与OP的问题不同,但确实确实回答了查找您所在容器的常见情况(如果有的话)。
特别是,安装并阅读此bash脚本的代码,该代码似乎运行良好:
什么 -
sudo apt install virt-what
virt-what
在Ubuntu 16.04上不适用于1.14-1版本。需要补丁。
我已经将JJC的答案翻译成红宝石
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
在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
也许这可以解决问题:
if [ -z $(docker ps -q) ]; then
echo "There is not process currently running"
else
echo "There are processes running"
fi
那是你要的吗?希望对您有帮助=)
docker
显然,容器内部没有二进制文件。
docker
并访问主机的Docker套接字的情况下(例如gitlab docker-in-docker)会失败。