프로세스가 도커 컨테이너 내에서 실행 중인지 확인하는 방법


85

[업데이트 1] 일부 기능에서 TCP 커널 매개 변수를 변경하는 셸이 있지만 이제이 셸을 Docker 컨테이너에서 실행해야합니다. 즉, 셸이 컨테이너 내에서 실행되고 있음을 알고 커널 구성을 중지해야합니다.

이제 그것을 달성하는 방법을 잘 모르겠습니다 /proc/self/cgroup. 컨테이너 내부의 내용은 다음과 같습니다.

9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/

위의 플래그를 사용하여이 프로세스가 컨테이너 내에서 실행 중인지 확인할 수 있습니까?

[Updated2] : 또한 프로세스가 lxc / Docker 내부에서 실행되는지 확인 했지만이 경우 작동하지 않는 것 같습니다. /proc/1/cgroup내 컨테이너 의 내용 은 다음과 같습니다.

8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/

/ lxc / containerid 없음


아주 명확한 질문이 아닙니다. 왜 이것이 필요합니까?
Henk Langeveld 2014 년


@fish no / lxc / <containerid> 내 경우에는 업데이트 참조
harryz 2014 년

1
@HenkLangeveld 커널 매개 변수는 Docker 컨테이너에서 읽기 전용이므로 셸이 컨테이너 내에서 실행 중인지 확인하고 셸에서 커널 기능을 비활성화해야합니다. 업데이트를 참조하십시오.
harryz 2014 년

스크립트의 일부 단계는 커널 매개 변수를 수정하려고 시도하며 Docker에서 실행할 때 건너 뛰어야합니다. 맑은.
Henk Langeveld

답변:


68

Docker 컨테이너 내부에 있는지 확인하려면 /proc/1/cgroup. 마찬가지로 이 게시물 제안 당신은 다음에 할 수 있습니다 :

여기에서 볼 수 있듯이 도커 컨테이너 외부에서는 모든 항목이 /proc/1/cgroup/납니다.

vagrant@ubuntu-13:~$ cat /proc/1/cgroup
11:name=systemd:/
10:hugetlb:/
9:perf_event:/
8:blkio:/
7:freezer:/
6:devices:/
5:memory:/
4:cpuacct:/
3:cpu:/
2:cpuset:/

Docker 컨테이너 내부에서 일부 제어 그룹은 Docker (또는 LXC)에 속합니다.

vagrant@ubuntu-13:~$ docker run busybox cat /proc/1/cgroup
11:name=systemd:/
10:hugetlb:/
9:perf_event:/
8:blkio:/
7:freezer:/
6:devices:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2
5:memory:/
4:cpuacct:/
3:cpu:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2
2:cpuset:/

@Founder 대답은 청소기
스콧 Stensland

5
"도커 컨테이너 외부에서 / proc / 1 / cgroup의 모든 항목은 /에서 끝납니다"라는 것은 엄격히 사실이 아닙니다. 예를 들어 우분투 16.04에서는 다음이 있습니다.12:perf_event:/ 11:blkio:/init.scope 10:cpuset:/ 9:devices:/init.scope 8:hugetlb:/ 7:cpu,cpuacct:/init.scope 6:net_cls,net_prio:/ 5:memory:/init.scope 4:pids:/init.scope 3:rdma:/ 2:freezer:/ 1:name=systemd:/init.scope
samfr

이것은 Linux에서만 작동하며 Darwin 또는 procfs를 사용하지 않는 다른 BSD에서는 작동하지 않습니다.
Christian

@Christian Docker / LXC는 Linux 전용이므로 괜찮습니다 :)?
Robert Lacroix

@RobertLacroix 그래서 procfs를 찾지 못하면 Docker에 있지 않습니까? 글쎄, 그건 충분히 공평하다고 생각합니다 ...
Christian

107

Docker 는 컨테이너의 디렉토리 트리 상단에 .dockerenv.dockerinit( v1.11에서 제거됨 ) 파일을 생성하므로 파일이 존재하는지 확인할 수 있습니다.

이와 같은 것이 작동합니다.

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

1
물론, 당신이나 다른 누군가가 /.dockerinit당신의 호스트에서 (아마도 우연히) 생성 한 경우가 아니라면, 컨테이너 밖에서 잘못 될 것입니다.
sosiouxme 2015

18
다른 누군가가 그것을 만들었다면 / 그들은 루트이며 당신이 도커에 있는지 아닌지를 아는 것보다 더 나쁜 문제가 있습니다.
davey

15
/.dockerenv장기적으로 의지하십시오 . 이런 식으로 사용하기위한 것이 아닙니다 .
ReactiveRaven

fwiw, Podman은 /.dockerenv. 그것은 생성 /run/.containerenv하지만 유사한 논리에 의해 신뢰할 수없는 구현 세부 사항처럼 들립니다. 일부 podman 별 대안 은 github.com/containers/libpod/issues/3586 을 참조하세요 .
Beni Cherniavsky-Paskin

21

코드로서의 Thomas의 솔루션 :

running_in_docker() {
  (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input)
}

노트

read더미 변수를위한이 단순한 관용구이다 합니까이 어떠한 출력을 생성? . 이것은 장황 할 수있는 것을 grep또는 패턴 테스트awk 로 바꾸는 간결한 방법입니다 .

읽기에 대한 추가 참고 사항


10
예외는 ... 일부 환경에서는 실패 3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope합니다. 예를 들어 일치하지 않기 때문 입니다. 더 간단합니다 grep -q docker /proc/1/cgroup. 그것의 결과 코드도 충분해야합니다.
larsks

2
read힘 작업 bash,하지만 가장 많이 사용에서 dash사용 중 하나를해야 쉘 read dummy(또는 유사) 또는 같은 구조를 사용[ -n "$(command)" ]
다니엘 알더

@DanielAlder 좋은 캐치, 다니엘. 텍스트를 업데이트하겠습니다.
Henk Langeveld 2015 년

1
이전에 이것은 Bourne 호환 쉘이 read변수 이름이없는 일반 을 지원한다고 주장했습니다 . 이것은 bash 및 ksh93에만 해당됩니다. Opengroup 은 최소한 하나의 변수없이 동작을 지정 read var하고 언급하지 않습니다 read. 에서 의 bashksh93의 , 어떤 경우 VAR이 지정되지 않은, 사용을 쉘 변수를 읽을 REPLY.
Henk Langeveld 2015 년

1
왜 그냥 사용할 수 awk -F: '$3 ~ /docker/' /proc/self/cgroup | read없습니까? 나를 위해 작동합니다.
Shubham Chaudhary

21

프로세스의 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)

이것은 당신이 용기에 있는지 아닌지를 구별하는 데 도움이됩니다. 예를 들어 다음을 수행 할 수 있습니다.

if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then {
    echo in docker
} else {
    echo not in docker
} fi

이것은 실제로 매우 귀중한 정보입니다. 감사
파비안 랭

4
OS에 따라 "init"를 "systemd"로 바꿔야 할 수도 있습니다. systemd에 대한 자세한 정보는 여기 .
BrianV

2
@BrianV에서 언급했듯이 이것은 나에게도 작동하지 않습니다.
Shubham Chaudhary

5
k8s 클러스터에서 실행되는 Docker 컨테이너에서을 head -n1 /proc/1/sched반환 하므로이 dumb-init (1, #threads: 1)답변에서 제안한 검사가 실패합니다. (또한 대답이 제안하는 것과는 반대로 PID는 컨테이너에서이 작업을 수행하고 있지만 해당 줄에서 "1"로 표시됩니다.)
Stefan Majewsky

이것은 확실히 보편적 인 해결책이 아닙니다. 당신은 당신이 할 경우 컨테이너의 PID 1. 예에 대해 원하는대로 사용 (정렬) 할 수 docker run --init ...는있을 것입니다 docker-init. 예를 들어 docker run ... head -n 1 /proc/1/sched그렇게하면 head.
jpkotta

6

나를 위해 작동하는 것은 '/'의 inode 번호를 확인하는 것입니다. 도커 내부에는 매우 많은 수가 있습니다. 도커 외부에서는 '2'와 같이 매우 낮은 숫자입니다. 이 접근 방식은 사용중인 파일 시스템에 따라 달라집니다.

도커 내부 :

# ls -ali / | sed '2!d' |awk {'print $1'}
1565265

Docker 외부

$ ls -ali / | sed '2!d' |awk {'print $1'}
2

스크립트에서 :

#!/bin/bash
INODE_NUM=`ls -ali / | sed '2!d' |awk {'print $1'}`
if [ $INODE_NUM == '2' ];
then
        echo "Outside the docker"
else
        echo "Inside the docker"
fi

MSYS2 ls -ali / | sed '2! d'| awk { 'print $ 1'} 232779805740174872
bo0k

과 같 ls -di /습니까? inode num이 다른 플랫폼에서 신뢰할 수없는 것 같습니다
yurenchen

이것이 제가 Xen domU 호스트와 도커 컨테이너를 구별하는 데 도움이 된 유일한 방법입니다
Michael Altfield

1

컨테이너에서 실행되는 프로세스를 제외해야했지만 docker cgroup 만 확인하는 대신 /proc/<pid>/ns/pid에서 init 시스템 과 비교 하기 로 결정 했습니다 /proc/1/ns/pid. 예:

pid=$(ps ax | grep "[r]edis-server \*:6379" | awk '{print $1}')
if [ $(readlink "/proc/$pid/ns/pid") == $(readlink /proc/1/ns/pid) ]; then
   echo "pid $pid is the same namespace as init system"
else
   echo "pid $pid is in a different namespace as init system"
fi

또는 우리의 경우 프로세스가 컨테이너에 없으면 오류를 생성하는 하나의 라이너를 원했습니다.

bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"

다른 프로세스에서 실행할 수 있으며 종료 코드가 0이면 지정된 PID가 다른 네임 스페이스에서 실행 중입니다.


나를 위해 작동하지 않습니다. K8S 스케줄 도커 용기 내에서 readlink /proc/self/ns/pidreadlink /proc/1/ns/pid동일한 출력을 생성한다.
Stefan Majewsky

1
@StefanMajewsky 컨테이너 런타임에서 활성화 된 기능을 확인 하기 위해 github.com/jessfraz/amicontained 를 사용해 볼 수 있습니다.
Greg Bray

0

SELinux 사용에 대한 Dan Walsh의 의견을 기반으로 ps -eZ | grep container_t하지만 ps설치할 필요 가 없습니다.

$ podman run --rm fedora:31 cat /proc/1/attr/current
system_u:system_r:container_t:s0:c56,c299
$ podman run --rm alpine cat /proc/1/attr/current
system_u:system_r:container_t:s0:c558,c813
$ docker run --rm fedora:31 cat /proc/1/attr/current
system_u:system_r:container_t:s0:c8,c583
$ cat /proc/1/attr/current
system_u:system_r:init_t:s0

이것은 단지 당신이 실행중인 알려줍니다 용기,하지만 어떤 런타임.

다른 컨테이너 런타임을 확인하지 않았지만 https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes 가 더 많은 정보를 제공하고 이것이 널리 사용 된다는 것을 제안 하며 rkt 및 lxc에서도 작동 할 수 있습니까?


-1

작은 파이썬 스크립트를 만들었습니다. 누군가가 유용하다고 생각하기를 바랍니다. :-)

#!/usr/bin/env python3
#@author Jorge III Altamirano Astorga 2018
import re
import math

total = None
meminfo = open('/proc/meminfo', 'r')
for line in meminfo:
    line = line.strip()
    if "MemTotal:" in line:
        line = re.sub("[^0-9]*", "", line)
        total = int(line)
meminfo.close()
print("Total memory: %d kB"%total)

procinfo = open('/proc/self/cgroup', 'r')
for line in procinfo: 
    line = line.strip()
    if re.match('.{1,5}:name=systemd:', line):
        dockerd = "/sys/fs/cgroup/memory" + \
            re.sub("^.{1,5}:name=systemd:", "", line) + \
            "/memory.stat"
        #print(dockerd)
        memstat = open(dockerd, 'r')
        for memline in memstat:
            memline = memline.strip()
            if re.match("hierarchical_memory_limit", memline):
                memline = re.sub("[^0-9]*", \
                    "", memline)  
                total = math.floor(int(memline) / 2**10)
        memstat.close()
procinfo.close()
print("Total available memory to the container: %d kB"%total)

멋지지만 컨테이너 안에 있는지 여부를 확인하는 것이 어떻게 도움이됩니까?
user528025

FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'
Scrooge McDuck
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.