如何确定进程是否在LXC/Docker容器内运行?
简介
本文的主要目标是确定进程是否在容器中运行。我们讨论了几种方法,可以帮助我们将非容器机器从容器中过滤出来。我们使用简单的命令和一些特殊的内核文件来总结我们的观点。
先决条件
要在您的设置机器上实现本文的完整内容,您需要具备以下列出的先决条件:
Linux操作系统:Ubuntu
Docker守护进程和客户端
方法
下面列出了一些有助于识别机器的方法。该机器可能是容器或非容器。
使用环境变量
使用.dockerenv文件
使用控制组信息
使用CPU信息
使用进程ID。
使用Docker环境
环境变量用于保存/存储信息。信息可以是特定文件的路径、用户名、密码等。
在这里,我们将创建一个存储文本“DockerContainer”的环境变量。运行时,此环境变量将传递到容器镜像。
步骤1:创建Dockerfile
在这里,我们创建了一个Dockerfile的最小版本,这是满足我们创建带有环境变量的Docker镜像的要求所需的。
# the bash image we are using is Busybox:latest FROM busybox:latest #create an environment variable needed when starting this image as a container ENV TEST_ENV="Docker-Container"
步骤2:构建镜像
现在为这个Dockerfile构建一个Docker镜像。
示例
$ docker build -t env_test:latest.
输出
Sending build context to Docker daemon 2.048kB Step 1/2 : FROM busybox:latest ---> 9d5226e6ce3f Step 2/2 : ENV TEST_ENV="Docker-Container" ---> Running in b993407fa937 Removing intermediate container b993407fa937 ---> c9e931c275be Successfully built c9e931c275be Successfully tagged env_test:latest
步骤3:运行容器
在这里,我们运行了容器,并传递了环境变量。
$docker run -itd -e TEST_ENV="Docker-Container" --name cont env_test:latest
步骤4:检查您现在是否在容器中
$echo $TEST_ENV
现在让我们进入容器并再次检查
$docker exec -it cont sh /# echo $TEST_ENV
输出
Docker-Container
因此,这证明了我们位于Docker容器内。
使用.dockerenv文件
创建Docker容器时,会在容器的根目录下创建一个“.dockerenv”文件。因此,搜索此文件可以帮助我们了解我们是在Docker容器内还是容器外。
在非容器机器上:
$ ls -la | grep ./dockerenv
这没有输出,因此文件不存在。
现在尝试在容器机器上:
/ # ls -la | grep .dockerenv
输出
-rwxr-xr-x 1 root root 0 Dec 18 14:00 .dockerenv
因此,这证明我们位于容器中。
使用proc文件系统
特殊文件是Linux文件系统的重要组成部分。其中一个特殊系统是proc文件系统。它用于存储内核的状态。
我们在proc文件系统中具有控制组和CPU调度。控制组的信息存储在特定位置。这些组对于非容器和容器机器具有不同的数据。控制组的路径是 /proc/1/cgroup,CPU调度的路径是 /proc/1/sched
步骤1:非容器机器
非容器机器(例如Ubuntu)上这两个位置的数据:
示例
$ cat /proc/1/sched | head -n 1
输出
systemd (1, #threads: 1)
在控制组中。
示例
$ cat /proc/1/cgroup | head -n 1
输出
0::/init.scope
步骤2:容器机器
现在在容器中。
示例
/# cat /proc/1/sched | head -n 1
输出
bash (1, #threads: 1)
上述输出显示第一个调度程序是用于bash或容器中的入口点命令。但对于非容器机器,它是systemd(Ubuntu)。
对于控制组:
示例
/ # cat /proc/1/cgroup | head -n 1
输出
0::/
使用进程ID
Linux中的每个进程都有一个唯一的ID,称为PID。有一个进程kthread,它仅存在于基于非容器的机器上。它的PID固定为2。因此,通过检查PID 2,我们可以识别我们是否在容器中。
在非容器机器上
示例
$ ps 2
输出
PID TTY STAT TIME COMMAND 2 ? S 0:00 [kthreadd]
在容器机器上,它可能不会显示任何进程。除了kthread之外的进程也是可能的。
结论
使用内核文件被认为是上述所有方法中最好的方法。有时,对于Docker容器,.dockerinit文件用于了解您是否在容器中。