有没有办法确定进程(脚本)是否在lxc容器(~Docker运行时)内运行?我知道有些程序能够检测它们是否在虚拟机内运行,是否类似于lxc / docker?
答案 0 :(得分:136)
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
它实际上可以返回它被调用的容器类型。可能会有所帮助。
但不知道其他主要发行版。
答案 1 :(得分:130)
最可靠的方法是检查/proc/1/cgroup
。它将告诉您init进程的控制组,当您在容器中不时,对于所有层次结构,它将是/
。当你在里面一个容器时,你会看到一个锚点的名字;使用LXC / Docker容器,分别类似于/lxc/<containerid>
或/docker/<containerid>
。
答案 2 :(得分:16)
在新的ubuntu 16.04系统上,新的systemd&amp; lxc 2.0
sudo grep -qa container=lxc /proc/1/environ
答案 3 :(得分:13)
在bash脚本中检查docker的简明方法是:
#!/bin/bash
if grep docker /proc/1/cgroup -qa; then
echo I'm running on docker.
fi
答案 4 :(得分:9)
Handy Python函数检查是否在Docker中运行(仅限linux,obvs。):
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()
答案 5 :(得分:9)
我们使用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)
这有助于区分您是否在容器中。
答案 6 :(得分:6)
最简单的方法是检查环境。如果你有container=lxc
变量,那么你就在一个容器内。
否则,如果您是root用户,则可以尝试执行mknod
或mount
操作,如果失败,您很可能在容量已降低的容器中。
答案 7 :(得分:3)
我的回答仅适用于 Node.js进程,但对于偶然发现此问题寻找Node.js特定答案的访问者可能相关。
我遇到了同样的问题并依赖于/proc/self/cgroup
我仅为此目的创建了一个 npm包 - 来检测Node.js进程是否在Docker容器内运行。 / p>
containerized npm module将帮助您在Node.js.它目前尚未在Io.js中测试,但也可能在那里工作。
答案 8 :(得分:3)
在Python中检查上面的所有解决方案:
import os
import subprocess
def in_container():
# type: () -> bool
""" Determines if we're running in an lxc/docker container. """
out = subprocess.check_output('cat /proc/1/sched', shell=True)
out = out.decode('utf-8').lower()
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', None) is not None
]
return any(checks)
答案 9 :(得分:2)
Docker正在日益发展,所以我们不能肯定他们将来是否会保留.dockerenv .dockerinit
。
在大多数Linux风格中,init
是第一个启动的过程。但就容器而言,情况并非如此。
#!/bin/bash
if ps -p1|grep -q init;then
echo "non-docker"
else
echo "docker"
fi
答案 10 :(得分:1)
以测试/proc/*/cgroup
的可接受答案为基础。
awk -F: '$3 ~ /^\/$/ {c=1} END{ exit c }' /proc/self/cgroup
因此,要在脚本中使用,可以通过这种方式构造测试。
is_running_in_container() {
awk -F: '$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
答案 11 :(得分:0)
这个SO Q&amp; A:"Find out if the OS is running in a virtual environment";虽然与OP的问题不一样,但它确实回答了常见的情况,即找到你所在的容器(如果有的话)。
特别是,安装并阅读这个bash脚本的代码似乎运行得很好:
virt-what :
sudo apt install virt-what
答案 12 :(得分:0)
我已将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
答案 13 :(得分:0)
这是Ruby中的解决方案,
# Usage: DockerHelper.running_in_docker?
module DockerHelper
extend self
def running_in_docker?
!!(File.read("/proc/1/cgroup") =~ %r[^\d+:\w+:/docker/]) # !! => true/false
rescue Errno::ENOENT
false
end
end
如果您喜欢使用自己的代码进行测试,请here's a spec in the gist。
答案 14 :(得分:0)
这是一个古老的问题,但确实是一个好问题。 :)
我已经编写了一些自动化脚本,这些脚本在裸机,VM和Docker容器中运行,并根据脚本在哪个平台上执行而进行逻辑分支。就我而言,我有创建容器和docker映像的特权,因此,只有在您控制整个堆栈的情况下,此解决方案才有效:
Dockerfile的片段:
FROM ubuntu:18.04
ENV PLATFORM="docker"
RUN apt update; \
...
然后,脚本可以仅检查$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
为了简洁起见,我在上面的代码中省略了裸机。
答案 15 :(得分:0)
golang代码获取pid container_id,您可以获取地图container_id获取docker image
func GetContainerID(pid int32) string {
cgroupPath := fmt.Sprintf("/proc/%s/cgroup", strconv.Itoa(int(pid)))
return getContainerID(cgroupPath)
}
func GetImage(containerId string) string {
if containerId == "" {
return ""
}
image, ok := containerImage[containerId]
if ok {
return image
} else {
return ""
}
}
func getContainerID(cgroupPath string) string {
containerID := ""
content, err := ioutil.ReadFile(cgroupPath)
if err != nil {
return containerID
}
lines := strings.Split(string(content), "\n")
for _, line := range lines {
field := strings.Split(line, ":")
if len(field) < 3 {
continue
}
cgroup_path := field[2]
if len(cgroup_path) < 64 {
continue
}
// Non-systemd Docker
//5:net_prio,net_cls:/docker/de630f22746b9c06c412858f26ca286c6cdfed086d3b302998aa403d9dcedc42
//3:net_cls:/kubepods/burstable/pod5f399c1a-f9fc-11e8-bf65-246e9659ebfc/9170559b8aadd07d99978d9460cf8d1c71552f3c64fefc7e9906ab3fb7e18f69
pos := strings.LastIndex(cgroup_path, "/")
if pos > 0 {
id_len := len(cgroup_path) - pos - 1
if id_len == 64 {
//p.InDocker = true
// docker id
containerID = cgroup_path[pos+1 : pos+1+64]
// logs.Debug("pid:%v in docker id:%v", pid, id)
return containerID
}
}
// systemd Docker
//5:net_cls:/system.slice/docker-afd862d2ed48ef5dc0ce8f1863e4475894e331098c9a512789233ca9ca06fc62.scope
docker_str := "docker-"
pos = strings.Index(cgroup_path, docker_str)
if pos > 0 {
pos_scope := strings.Index(cgroup_path, ".scope")
id_len := pos_scope - pos - len(docker_str)
if pos_scope > 0 && id_len == 64 {
containerID = cgroup_path[pos+len(docker_str) : pos+len(docker_str)+64]
return containerID
}
}
}
return containerID
}
答案 16 :(得分:-3)
也许这就是诀窍:
if [ -z $(docker ps -q) ]; then
echo "There is not process currently running"
else
echo "There are processes running"
fi
这就是你想要的吗?帮助它帮助=)