यह जांचने के लिए कि क्या एक प्रक्रिया डॉक कंटेनर के अंदर चल रही है


85

[Updated1] मेरे पास एक शेल है जो कुछ कार्यों में टीसीपी कर्नेल मापदंडों को बदल देगा, लेकिन अब मुझे इस शेल को डॉकटर कंटेनर में चलाने की आवश्यकता है, इसका मतलब है कि शेल को यह जानना होगा कि यह कंटेनर के अंदर चल रहा है और कर्नेल को कॉन्फ़िगर करना बंद कर दें।

अब मुझे यकीन नहीं है कि कैसे हासिल किया जाए, यहाँ /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 / कंटेनड


बहुत स्पष्ट सवाल नहीं है। आप इसकी आवश्यकता क्यों है?
हेंक लैंगवेल्ड


@fish no / lxc / <कंटेनड> मेरे मामले में, अपडेट देखें
harryz

1
@HenkLangeveld कर्नेल पैरामीटर केवल-डॉकर कंटेनर में पढ़ा जाता है, इसलिए मुझे यह जानने की आवश्यकता है कि क्या मेरा शेल कंटेनर के अंदर चल रहा है और मेरे शेल में कर्नेल फ़ंक्शन अक्षम करता है। अपडेट देखें
harryz

स्क्रिप्ट के कुछ चरण कर्नेल मापदंडों को संशोधित करने का प्रयास करते हैं, और डॉकर में चलने पर इसे छोड़ने की आवश्यकता होती है। स्पष्ट।
हेंक लैंगवेल्ड

जवाबों:


68

एक डॉकटर कंटेनर के अंदर की जाँच करने के लिए यदि आप डॉकटर कंटेनर के अंदर हैं या नहीं /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:/

डॉकटर कंटेनर के अंदर कुछ नियंत्रण समूह डोकर (या 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 का उत्तर क्लीनर है
स्कॉट स्टेंसलैंड

5
यह कड़ाई से सच नहीं है कि "डॉकटर कंटेनर के बाहर / प्रॉप / 1 / cgroup अंत में सभी प्रविष्टियाँ /"। Ubuntu 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

यह बहुत अधिक केवल लिनक्स पर काम करता है, डार्विन या अन्य बीएसडी पर नहीं जो कि एक खरीद का उपयोग नहीं करता है।
क्रिश्चियन

@ क्रिसियन डोकर / LXC केवल चीजें हैं, तो यह ठीक है, ठीक है :)?
राबर्ट लैक्रोइक्स

@RobertLacroix तो आप कह रहे हैं कि अगर आपको कोई खरीद नहीं मिली, तो आप डॉकर में नहीं हैं? ठीक है, यह पर्याप्त है जो मुझे लगता है ...
ईसाई

107

डॉकटर बनाता है .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अपने मेजबान (शायद दुर्घटना से) पर बनाया है , उस स्थिति में यह कंटेनर के बाहर गलत होगा।
सोसिओक्मे

18
अगर किसी और ने इसे बनाया है / तो वे जड़ हैं और आपको यह जानने की तुलना में बदतर समस्याएं हैं कि आप docker में हैं या नहीं।
davey

15
/.dockerenvलंबी अवधि में भरोसा करने से बचें । यह इस तरह से इस्तेमाल करने का इरादा नहीं है
प्रतिक्रियाशील

fwiw, Podman नहीं बनाते हैं /.dockerenv। यह बनाता है /run/.containerenvलेकिन इसी तरह के तर्क से, कार्यान्वयन विस्तार की तरह लगता है पर भरोसा नहीं किया जा सकता है। कुछ पॉडमैन-विशिष्ट विकल्पों के लिए github.com/containers/libpod/issues/3586 देखें ।
बेनी चेर्नियाव्स्की-पास्किन

21

कोड के रूप में थॉमस का समाधान:

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

ध्यान दें

readएक डमी चर के साथ के लिए एक सरल मुहावरा है यह क्या किसी भी उत्पादन का उत्पादन? । यह एक संभवतः वर्बोज़ मोड़ के लिए एक कॉम्पैक्ट विधि है grepया awkएक में परीक्षण एक पैटर्न की।

पढ़ने पर अतिरिक्त ध्यान दें


10
सिवाय ... यह कुछ envrionments में विफल हो जाएगा, क्योंकि, उदाहरण के लिए, 3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scopeमेल नहीं खाता। को सरल grep -q docker /proc/1/cgroup; उस से परिणाम कोड भी पर्याप्त होना चाहिए।
लार्क्स

2
readके लिए काम कर सकते हैं bash, लेकिन सबसे अधिक इस्तेमाल किए जाने वाले dashशेल में आपको या तो read dummy(या समान) का उपयोग करना होगा या एक निर्माण का उपयोग करना होगा जैसे[ -n "$(command)" ]
डैनियल एल्डर

@ डैनियलअल्ड अच्छा कैच, डैनियल। मैं पाठ को अपडेट करूंगा।
हेंक लैंगवेल्ड 19

1
पहले यह दावा किया गया था कि कोई भी बॉर्न संगत शेल readचर नाम के बिना सादे का समर्थन करता है । यह केवल बैश और ksh93 के लिए सच है। Opengroup केवल निर्दिष्ट read varकरता है और readकम से कम एक चर के बिना व्यवहार का उल्लेख नहीं करता है । में पार्टी और ksh93 , अगर कोई वर दिया जाता है, का उपयोग करता है खोल चर पढ़ा REPLY
हेनक लैंगवेल्ड

1
हम सिर्फ इस्तेमाल क्यों नहीं कर सकते awk -F: '$3 ~ /docker/' /proc/self/cgroup | read? मेरे लिये कार्य करता है।
शुभम चौधरी

21

हम प्रक्रिया के PID को निकालने के लिए proc की अनुसूची (/ proc / $ PID / अनुसूची) का उपयोग करते हैं। कंटेनर के अंदर प्रक्रिया की पीआईडी ​​अलग होगी फिर यह मेजबान (एक गैर-कंटेनर प्रणाली) पर पीआईडी ​​है।

उदाहरण के लिए, कंटेनर पर / proc / 1 / शेड्यूल का आउटपुट वापस आएगा:

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" के साथ बदलने की आवश्यकता हो सकती है। सिस्टमडे पर अधिक जानकारी यहाँ
ब्रायन वी

2
जैसा कि @BrianV द्वारा उल्लेख किया गया है, यह मेरे लिए भी काम नहीं करता है।
शुभम चौधरी

5
K8s क्लस्टर पर चल रहे डॉकटर कंटेनर में, head -n1 /proc/1/schedरिटर्न होता है dumb-init (1, #threads: 1), इसलिए इस उत्तर में दिया गया चेक विफल हो जाता है। (इसके अलावा, इसका उत्तर क्या है, इसके विपरीत, पीआईडी ​​को उस पंक्ति में "1" के रूप में दिखाया गया है, हालांकि मैं एक कंटेनर में ऐसा कर रहा हूं।)
स्टीफन माजूस्की

यह निश्चित रूप से एक सार्वभौमिक समाधान नहीं है। आप कंटेनर के पीआईडी ​​1 के लिए जो चाहें उपयोग कर सकते हैं (सॉर्ट) 1. यदि आप ऐसा करते docker run --init ...हैं docker-init। आप जैसे करते हैं docker run ... head -n 1 /proc/1/schedयह हो जाएगा head
jpkotta

6

मेरे लिए क्या काम करता है '/' के इनकोड नंबर की जांच करना। डॉकटर के अंदर, इसकी बहुत अधिक संख्या है। कर्ता के बाहर, इसकी संख्या बहुत कम है जैसे '2'। मुझे लगता है कि यह दृष्टिकोण भी इस्तेमाल किया जा रहा FileSystem पर निर्भर करेगा।

उदाहरण

कर्ता के अंदर:

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

कर्ता के बाहर

$ 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

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

के रूप में ही ls -di /? लगता है कि अलग मंच पर
इनोड

यह केवल एक चीज है जिसने मेरे लिए एक
एक्सएम डोमू

1

हमें कंटेनरों में चलने वाली प्रक्रियाओं को बाहर करने की जरूरत थी, लेकिन हमने केवल dog cgroups के लिए जाँच करने के बजाय /proc/<pid>/ns/pidinit सिस्टम की तुलना करने का निर्णय लिया /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)"

जिसे हम किसी अन्य प्रक्रिया से निष्पादित कर सकते हैं और यदि निकास कोड शून्य है तो निर्दिष्ट PID एक अलग नामस्थान में चल रहा है।


मेरे लिए काम नहीं करता है। एक k8s-Docker कंटेनर के भीतर से, readlink /proc/self/ns/pidऔर readlink /proc/1/ns/pidएक ही आउटपुट का उत्पादन करें।
स्टीफन माज्यूस्की

1
@StefanMajewsky कंटेनर रनटाइम में क्या विशेषताएं सक्षम हैं, यह देखने के लिए github.com/jessfraz/amicontain का उपयोग करने का प्रयास करना चाह सकते हैं ।
ग्रेग ब्रे

0

SELinux का उपयोग करने के बारे में डैन वॉल्श की टिप्पणी के आधार पर 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'
स्क्रूज मैकडक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.