如何确定进程是否在lxc / Docker中运行?

时间:2013-11-15 20:42:05

标签: linux bash docker

有没有办法确定进程(脚本)是否在lxc容器(~Docker运行时)内运行?我知道有些程序能够检测它们是否在虚拟机内运行,是否类似于lxc / docker?

17 个答案:

答案 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用户,则可以尝试执行mknodmount操作,如果失败,您很可能在容量已降低的容器中。

答案 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

这就是你想要的吗?帮助它帮助=)