有什么方法可以确定一个进程(脚本)是否在lxc容器中运行(~ Docker runtime)?我知道一些程序能够检测它们是否在虚拟机中运行,lxc/docker是否也有类似的功能?
当前回答
这是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
如果您喜欢对代码进行测试,这里有一个要点说明。
其他回答
在bash脚本中检查docker/lxc的一个简单方法是:
#!/bin/bash
if grep -sq 'docker\|lxc' /proc/1/cgroup; then
echo "I am running on Docker."
fi
截至2022年,在lxd v4.0+中,到目前为止,没有一个答案可以同时适用于docker和lxc。
dockerenv文件不适用于非docker容器。 检查/proc/1/cgroup中的所有层次结构都是/有点可能工作。然而,非容器上的一些层次结构是/init。scope (Ubuntu 20.04 cgroup 0和1).所以也不完全可靠。 在/proc/1/environ中检查container=lxc适用于lxc,但不适用于docker。此外,它还需要根权限。
到目前为止,我发现唯一一种在CentOS和Ubuntu上使用lxc(4.0)容器和Docker可靠工作的方法,而且不需要root权限,就是检查PID 2。
在所有主机系统中,PID 2是kthread:
$ ps -p 2
PID TTY TIME CMD
2 ? 00:00:00 kthreadd
在容器中,这个PID要么不存在,要么不是kthread。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
我的回答只适用于Node.js进程,但可能与一些无意中遇到这个问题并寻找Node.js特定答案的访问者相关。
我也遇到了同样的问题,我在/proc/self/cgroup上创建了一个npm包,专门用于检测一个Node.js进程是否在Docker容器中运行。
容器化的npm模块将在Node.js中帮助你。它目前还没有在Io.js中测试,但也可以在那里工作。
golang代码得到pid container_id,你可以得到map container_id get 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
}
在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
推荐文章
- 如何获得一个变量值,如果变量名存储为字符串?
- 拉访问拒绝存储库不存在或可能需要docker登录
- 如何在ENTRYPOINT数组中使用Docker环境变量?
- Docker:容器不断地重新启动
- RVM不是一个函数,用' RVM use…’不会起作用
- 如何强制从另一个SSH会话分离屏幕?
- 如何打破一个循环在Bash?
- 如何从终端机发送电子邮件?
- 如何将文件指针(file * fp)转换为文件描述符(int fd)?
- Mac/OS X上的/var/lib/docker在哪里
- 如何用docker-compose标记docker图像
- Linux Bash中双&和分号有什么区别?
- 在Bash中模拟do-while循环
- 在Bash中将输出赋给变量
- 在SSH会话中查找客户端的IP地址