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


172

프로세스 (스크립트)가 lxc 컨테이너 내에서 실행되는지 확인하는 방법이 있습니까 (~ Docker runtime)? 일부 프로그램이 가상 시스템 내에서 실행되는지 여부를 감지 할 수 있다는 것을 알고 있습니다.


현명하지 않은 것처럼 보일 수도 있지만, 문제를 설명하고 해결 방법을 묻는 질문을 바꾸는 것이 가장 좋습니다. 많은 경우에 그러한 변경을하기는 어렵지만 당신이 원한다면 간단히 말로 바꾸는 것은 어렵지 않습니다.
mah

반면 컨테이너 내부에서이 명령을 실행 흥미로운 반응이있다 : 가동 시간
스콧 Stensland

답변:


169

가장 신뢰할 수있는 방법은 확인하는 것 /proc/1/cgroup입니다. 그것은 당신에게 init 프로세스의 컨트롤 그룹을 알려줄 것이고 당신이 컨테이너에 있지 않을 때는 /모든 계층을위한 것입니다. 컨테이너 안에 있으면 앵커 포인트의 이름이 표시됩니다. LXC / Docker 컨테이너를 사용하면 비슷 /lxc/<containerid>하거나 /docker/<containerid>각각 비슷 합니다.


13
docker는 이제 그 경로 docker대신에 사용 lxc합니다
Andy

4
lxd / lxc 컨테이너에서는 작동하지 않지만 stackoverflow.com/a/20010626/170230 에서는 작동합니다.
Draco Ater

이후 버전의 systemd에서는 /모든 cgroup에 사용하는 프로세스 1에 의존 할 수없는 것처럼 보입니다 . 내 데비안 9 시스템 (시스템 232)에서는 열 개의 cgroup ( 3:cpuset, 4:perf_event7:freezer) 중 세 개만 루트에 있습니다. 나머지는 아래에 /init.scope있습니다. 즉, 해당 파일을 검색하는 :/docker/것이 현재 가장 신뢰할 수있는 휴리스틱 이라고 생각합니다 .
cjs

2
grep 'docker\|lxc' /proc/1/cgroupDocker 18.09에서 나를 위해 일합니다.
rypel 2019

1
나를 위해 작동하지 않습니다. LXC 권한 컨테이너를 사용하는 호스트 Ubuntu 19.04, 게스트 Ubuntu 18.04. / proc / 1 / cgroup에 lxc 문자열이 없습니다.
Gab

157

Docker는 .dockerenv컨테이너 내부의 디렉토리 트리 루트에 파일을 만듭니다 . 이 스크립트를 실행하여 확인할 수 있습니다

#!/bin/bash
if [ -f /.dockerenv ]; then
    echo "I'm inside matrix ;(";
else
    echo "I'm living in real world!";
fi


더 : 우분투는 실제로 bash 스크립트를 가지고 있으며 /bin/running-in-container실제로 호출 된 컨테이너 유형을 반환 할 수 있습니다. 도움이 될 수 있습니다. 그래도 다른 주요 배포판에 대해서는 모른다.


13
중요 사항 : 최신 버전의 Docker에서.dockerinit 파일이 제거 되었으므로이 방법은 더 이상 작동하지 않습니다. 이 글을 쓰는 시점에서 .dockerenv파일은 계속 유지되므로 대신 사용할 수 있습니다.
Jason R

On Debian /bin/running-in-container은에서 제공합니다 upstart. systemd로 전환하면 사라질 수 있습니다. 도움이되지 않기를 바랍니다.
Max Murphy

"디렉토리 트리의 맨 위에"는 무엇을 의미합니까? 어디있어?
Alexander Mills

3
다른 사람들은 점검 .dockerenv권장되지 않는다고
Dave

1
참고 : .dockerenv 테스트는 런타임이 docker 디먼 인 경우에만 작동합니다. podman 또는 다른 것을 사용하는 경우 실패합니다.
Benjamin Kircher

22

새로운 우분투 16.04 시스템, 새로운 systemd & lxc 2.0

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

이것은 Ubuntu focal 20.04에서 작동합니다. 이 시점 이상의 답변은 없습니다.
Jonathan Hartley

16

bash 스크립트에서 docker를 확인하는 간결한 방법은 다음과 같습니다.

#!/bin/bash
if grep docker /proc/1/cgroup -qa; then
   echo I'm running on docker.
fi

14

Docker에서 실행 중인지 확인하는 편리한 Python 함수 :

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

2
중요 사항! 컨테이너가 kubernetes에서 실행될 때는 작동하지 않는 것 같습니다. 대신 'docker'대신 마지막 줄을 'kubepod'로 바꾸십시오. (또는 둘 다 검사하는 "또는"문을 넣으십시오.)
JJC

1
그것은이다 kubepods같아요.
rookie099

9

프로세스의 PID를 추출하기 위해 proc의 sched (/ proc / $ PID / sched)를 사용합니다. 컨테이너 내부의 프로세스 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)

컨테이너에 있는지 여부를 구별하는 데 도움이됩니다.


OS에 따라 "init"를 "systemd"로 바꿔야 할 수도 있습니다. systemd에 대한 자세한 내용은 여기를 참조하십시오 .
BrianV 2016 년

예, 그러나 포인트는 init 프로세스의 이름이 아니고 포인트는 프로세스 번호였습니다.
MillerGeek

이것은 Docker에서만 작동하는 것 같습니다. LXC 컨테이너
Systemd

도커에서도 1을 반환합니다. 그것은 일반적으로 sh하지 init가 있지만, 하나의 거의 모든 것을 할 수있다.
Jan Hudec

도커에서, 이것은 더 이상 사실이 아닙니다bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
shalomb

5

가장 쉬운 방법은 환경을 확인하는 것입니다. container=lxc변수 가 있으면 컨테이너 내에 있습니다.

그렇지 않으면 루트 인 경우 수행 mknod또는 mount조작을 시도 할 수 있으며 , 실패하면 기능이 떨어지는 컨테이너에있을 가능성이 높습니다.


이것은 도커뿐만 아니라 (나는 그것을 확인하지 않았 음) 작동하지만 더 중요한 것은 lxd / lxc 컨테이너 (체크 됨)에서 /proc/1/cgroup작동합니다.
Draco Ater

2
의사 코드 대신 코드로 답변을 편집 할 수 있습니까? "container = lxc"?는 적절한 것이 아닙니다. [[ "lxc"= "$ container"]]와 같은 의미입니까?
Alexander Mills

3
내 말은 ... 이상하다. 보통 env 변수는 모든 대문자로되어있다. 여기서 정밀도를 찾는다
Alexander Mills

7
docker run alpine env변수처럼 보이는 것은 없습니다
Archimedes Trajano

3

내 답변은 Node.js 프로세스 에만 적용 되지만 Node.js 관련 답변을 찾는이 질문에 걸려 넘어지는 일부 방문자에게는 관련이있을 수 있습니다.

동일한 문제가 있었고 Node.js 프로세스가 Docker 컨테이너 내에서 실행되는지 여부를 감지하기 위해이 목적으로 만 npm 패키지/proc/self/cgroup만들었습니다 .

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


이 모듈에 감사드립니다. 보류중인 두 가지 수정 프로그램 인 것 같습니다. 계속 유지하고 있습니까?
stevokk

2

파이썬에서 위의 모든 솔루션을 확인하십시오.

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

이것은 Mac 기반 도커 컨테이너에서 작동하지 않았습니다. 비어 있습니다. Docker 버전 2.1.0.1 (37199).
splintercell

이 사람은 한 : def is_non_docker(): return os.path.exists('/proc/1/cgroup')여기 허용 대답에 따라 stackoverflow.com/questions/20010199/...
splintercell

2
쓸모없는 고양이 사용 상을받습니다. 그리고 서브 프로세스 하나의 쓸모없는 사용.
Jan Hudec

예, 이것은 완전히 새로운 수준의 불필요한 것입니다 cat! 좋은 것
-D

당신이 옳습니다, 나는 여전히 모든 것을 포괄하지는 않지만 대답을 업데이트 할 것입니다. @ JanHudec
blakev

1

Docker는 날마다 진화하고 있으므로 .dockerenv .dockerinit앞으로 계속 유지할지 확실하지 않습니다 .

대부분의 Linux 특징 init은 시작하는 첫 번째 프로세스입니다. 그러나 컨테이너의 경우 이것은 사실이 아닙니다.

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

6
@RomanTrofimov LXC / Docker도 마찬가지입니다. 정말 재미있는 의견입니다.
abourget

1
centos 7에서도 작동하지 않습니다. 호스트 컴퓨터에서 실행하면 docker라고 표시됩니다. systemd가 프로세스 ID 1로 실행중인 것 같습니다
Venkateswara Rao

@VenkateswaraRao-컨테이너 내부에서 실행해야합니다. 도커 컨테이너 내부에 있는지 여부를 확인하는 것이 목적입니다.
Govind Kailas

1
@GovindKailas : 문제는 이것이 정상적인 PID 하나가 있다고 가정이다 init에 진실하지 않은, systemd또는 launchd... 기반 시스템
게르트 반 덴 베르그

3
@SamThomas : 시작, 시작, Solaris SMF, 시스템, Sys V 스타일 초기화, BSD 스타일 초기화 (이 둘 중 일부는 PID 1을 호출 할 수 있음 init), OpenRC, initng, runit. 여기를 참조하십시오 . 대부분의 최신 리눅스 기반의 시스템을 사용하는 것이 systemd일부 오래된 것들, 신출내기 .... 모든 현대의 OS X 시스템을 사용하는 것,launchd
거트 반 베르그 덴

0

이 SO Q & A : "OS가 가상 환경에서 실행되고 있는지 확인하십시오" ; OP의 질문과 동일하지는 않지만 실제로 어떤 컨테이너에 있는지 (있는 경우) 찾는 일반적인 경우에 대답합니다.

특히,이 bash 스크립트의 코드를 설치하고 읽으십시오.

미덕 :

sudo apt install virt-what

virt-whatUbuntu 16.04의 버전 1.14-1 에서는 작동하지 않습니다 . 패치가 필요합니다.
Lucas

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

-1

도커 컨테이너에서 항목 /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

둘 다에 1을 반환합니다.
소린

-4

어쩌면 이것이 트릭을 할 수 있습니다.

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

너가 원하는게 그거야? 그것이 도움이되기를 바랍니다 =)


1
어떤 docker바이너리 분명, 용기의 내부에서 사용할 수 없습니다.
toriningen

3
음, 이것은 제어 컨테이너가 docker있고 호스트의 도커 소켓에 액세스하는 상황 (예 : gitlab docker-in-docker)에서 실패 합니다.
shalomb

1
네, 맞습니다. 물론 없습니다. ^^. 내가 읽을 때 질문에 대한 잘못된 해석을 얻었습니다. 감사합니다, 샬롬
Leonardo Da Vinci
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.