programing

프로세스가 lxc/Docker 내부에서 실행되는지 확인하는 방법은 무엇입니까?

mailnote 2023. 5. 11. 21:43
반응형

프로세스가 lxc/Docker 내부에서 실행되는지 확인하는 방법은 무엇입니까?

프로세스(스크립트)가 lxc 컨테이너(~ 도커 런타임) 내에서 실행되는지 확인할 수 있는 방법이 있습니까?일부 프로그램이 가상 시스템 내에서 실행되는지 여부를 감지할 수 있는 것으로 알고 있습니다. lxc/docker에서 비슷한 프로그램을 사용할 수 있습니까?

도커는 다음을 만듭니다..dockerenv컨테이너 내부의 디렉터리 트리 루트에 있는 파일입니다.▁an▁perform다▁this있니▁by습▁seen를 수행함으로써 알 수 있습니다.ls -la /.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호출된 컨테이너 유형을 반환할 수 있습니다.도움이 될 수도 있습니다.하지만 다른 주요 디스트로들에 대해서는 모릅니다.

가장 신뢰할 수 있는 방법은 확인하는 것입니다./proc/1/cgroup그것은 당신에게 init 프로세스의 제어 그룹을 알려줄 것이고, 당신이 컨테이너에 없을 때, 그것은/모든 계층에 대해.컨테이너 안에 있으면 앵커 포인트의 이름이 표시됩니다.LXC/도커 컨테이너를 사용하면 다음과 같습니다./lxc/<containerid>또는/docker/<containerid>각각 다음과 같다.

새로운 Ubuntu 16.04 시스템, 새로운 systemd & lxc 2.0

sudo grep -qa container=lxc /proc/1/environ

bash 스크립트에서 도커/lxc를 확인하는 간단한 방법은 다음과 같습니다.

#!/bin/bash
if grep -sq 'docker\|lxc' /proc/1/cgroup; then
   echo "I am running on Docker."
fi

Docker에서 실행 중인지 확인하는 핸디 파이썬 기능:

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()

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)

이것은 사용자가 컨테이너 안에 있는지 여부를 구분하는 데 도움이 됩니다.

가장 쉬운 방법은 환경을 확인하는 것입니다.만약 당신이 가지고 있다면.container=lxc변수입니다. 컨테이너 안에 있습니다.

그렇지 당신이 루트라면, 은 root를 수행하려고 할 수 .mknod또는mount작동이 실패할 경우 기능이 손실된 컨테이너에 있을 가능성이 높습니다.

2022년 현재 lxd v4.0+에서는 도커와 lxc 모두에 대해 지금까지 어떤 답변도 작동하지 않습니다.

  • A .dockerenv파일이 비캐리어 컨테이너에 대해 작동하지 않습니다.
  • 의 모든 계층 /proc/1/cgroup/효과가 있을지도 모릅니다.에 대한 구조는 그나비이일계입니다./init.scope(Ubuntu 20.04 cgroup 0 및 1).따라서 완전히 신뢰할 수 있는 것도 아닙니다.
  • 를 확인하는 입니다.container=lxc/proc/1/environlxc에서는 작동하지만 도커에서는 작동하지 않습니다.또한 루트 권한이 필요합니다.

지금까지 lxc(4.0) 컨테이너와 도커가 있는 CentOS와 Ubuntu 모두에서 안정적으로 작동하고 루트 권한이 필요하지 않은 유일한 방법은 PID 2를 확인하는 것입니다.

는 "PID 2"입니다.kthreadd:

$ ps -p 2
  PID TTY          TIME CMD
    2 ?        00:00:00 kthreadd

컨테이너에 이 PID가 없거나 kthread가 아닙니다.도커와 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

이것은 오래된 질문이지만, 정말 좋은 질문입니다.:)

베어메탈, VM 및 도커 컨테이너에서 실행되는 자동화 스크립트를 작성했으며 스크립트가 실행되는 플랫폼을 기반으로 논리적 분기를 수행했습니다.저의 경우 컨테이너와 도커 이미지를 모두 생성할 수 있는 권한이 있으므로 이 솔루션은 전체 스택을 제어하는 경우에만 작동합니다.

도커 파일의 일부:

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

간결하게 하기 위해 위 코드에서 베어메탈을 생략했습니다.

이 SOQ&A: "OS가 가상 환경에서 실행 중인지 확인하십시오." OP의 질문과 같지는 않지만, 실제로 현재 사용 중인 컨테이너를 찾는 일반적인 경우에 대한 답변입니다.

특히 이 bash 스크립트의 코드를 설치하고 잘 작동하는 것처럼 보이는 코드를 읽으십시오.

virt-what:

sudo apt install virt-what

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

내 답변은 Node.js 프로세스에만 적용되지만 Node.js 특정 답변을 찾는 일부 방문자에게 유용할 수 있습니다.

나도 같은 문제를 가지고 있었고 의존하고 있었습니다./proc/self/cgroupNode.js 프로세스가 Docker 컨테이너 내에서 실행되는지 여부를 탐지하기 위해 npm 패키지를 만들었습니다.

컨테이너화된 npm 모듈은 Node.js에서 당신을 도울 것입니다.현재 Io.js에서 테스트되지는 않았지만 Io.js에서도 작동할 수 있습니다.

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

도컨이너에서테항, 목커목 항목이 ./proc/self/cgroup호스트의 cgroup에 마운트됩니다.

예를 들어 용기에.

# 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

여기 루비에 대한 해결책이 있습니다.

# 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

코드로 테스트하는 것을 좋아한다면 요점에 있는 사양이 여기 있습니다.

골랑 코드는 pid container_id를 가져오고 맵 container_id는 도커 이미지를 가져올 수 있습니다.

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
}

약간 주제에서 벗어난 내용으로, 다음 두 가지 방법으로 컨테이너에 있는지 여부를 확인할 수 있습니다.

  1. cat /proc/1/environ|tr "\0" "\n"|grep container알게 될 것입니다container변수(컨테이너 안에 있는 경우).

  2. ps -ef | grep '\['컨테이너에 있을 때는 grep 프로세스만 볼 수 있습니다. 즉, 볼 수 있는 커널 프로세스가 없습니다(예:[kthreadd]). 주의: 일반 macOS도 커널 프로세스를 표시하지 않습니다.

참조: 이 리눅스 퀴즈 페이지

도커는 하루가 다르게 진화하고 있기 때문에 그들이 계속할지 확신할 수 없습니다..dockerenv .dockerinit미래에.

대부분의 리눅스 맛에서.init시작하는 첫 번째 프로세스입니다.그러나 컨테이너의 경우에는 그렇지 않습니다.

#!/bin/bash
if ps -p1|grep -q init;then  
  echo "non-docker" 
else 
  echo "docker" 
fi

어쩌면 이것이 효과가 있을 수도 있습니다.

if [ -z $(docker ps -q) ]; then
    echo "There is not process currently running"
else
    echo "There are processes running"
fi

그게 네가 원하는 거니?도움이 되길 바랍니다 =)

언급URL : https://stackoverflow.com/questions/20010199/how-to-determine-if-a-process-runs-inside-lxc-docker

반응형