[Updated1] Ich habe eine Shell, die in einigen Funktionen die TCP-Kernelparameter ändert, aber jetzt muss diese Shell im Docker-Container ausgeführt werden. Das bedeutet, dass die Shell wissen muss, dass sie in einem Container ausgeführt wird, und die Konfiguration des Kernels beenden muss.
Jetzt bin ich mir nicht sicher, wie ich das erreichen soll. Hier ist der Inhalt des /proc/self/cgroup
Behälters:
9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Kann ich mit den oben genannten Flags herausfinden, ob dieser Prozess in einem Container ausgeführt wird?
[Updated2]: Ich habe auch festgestellt, dass festgestellt wurde, ob ein Prozess in lxc / Docker ausgeführt wird , aber in diesem Fall scheint er nicht zu funktionieren. Der Inhalt in /proc/1/cgroup
meinem Container lautet:
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Nein / lxc / containerid
quelle
Antworten:
Das Überprüfen in einem Docker-Container, ob Sie sich in einem Docker-Container befinden oder nicht, kann über erfolgen
/proc/1/cgroup
. Wie dieser Beitrag vorschlägt, können Sie Folgendes tun:Außerhalb eines Docker-Containers
/proc/1/cgroup
enden alle Einträge am Ende,/
wie Sie hier sehen können:In einem Docker-Container gehören einige der Kontrollgruppen zu Docker (oder LXC):
quelle
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
Docker erstellt
.dockerenv
und( in Version 1.11 entfernt ) Dateien oben im Verzeichnisbaum des Containers, sodass Sie möglicherweise überprüfen möchten, ob diese vorhanden sind..dockerinit
So etwas sollte funktionieren.
#!/bin/bash if [ -f /.dockerenv ]; then echo "I'm inside matrix ;("; else echo "I'm living in real world!"; fi
quelle
/.dockerinit
auf Ihrem Host erstellt (möglicherweise aus Versehen). In diesem Fall ist dies außerhalb eines Containers falsch./.dockerenv
langfristig darauf. Es ist nicht für diese Verwendung vorgesehen ./.dockerenv
. Es erzeugt zwar,/run/.containerenv
aber nach ähnlicher Logik klingt es nach Implementierungsdetails, auf die man sich nicht verlassen kann. Unter github.com/containers/libpod/issues/3586 finden Sie einige podman-spezifische Alternativen.Wir verwenden den Zeitplan des Prozesses (/ proc / $ PID / sched), um die PID des Prozesses zu extrahieren. Die PID des Prozesses im Container unterscheidet sich von der PID auf dem Host (einem Nicht-Container-System).
Beispielsweise gibt die Ausgabe von / proc / 1 / sched für einen Container Folgendes zurück:
root@33044d65037c:~# cat /proc/1/sched | head -n 1 bash (5276, #threads: 1)
Auf einem Nicht-Container-Host:
$ cat /proc/1/sched | head -n 1 init (1, #threads: 1)
Dies hilft zu unterscheiden, ob Sie sich in einem Container befinden oder nicht. zB können Sie tun:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then { echo in docker } else { echo not in docker } fi
quelle
head -n1 /proc/1/sched
zurückdumb-init (1, #threads: 1)
, sodass die in dieser Antwort vorgeschlagene Prüfung fehlschlägt. (Entgegen der Antwort wird die PID in dieser Zeile als "1" angezeigt, obwohl ich dies in einem Container mache.)docker run --init ...
, wird dies der Fall seindocker-init
. Wenn Sie dies tundocker run ... head -n 1 /proc/1/sched
, wird es zhead
.Thomas 'Lösung als Code:
running_in_docker() { (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input) }
Hinweis
Die
read
Variable mit einem Dummy ist eine einfache Redewendung für Erzeugt dies eine Ausgabe? . Es ist eine kompakte Methode eines möglicherweise ausführlichen zum Drehengrep
oderawk
in einen Test eines Musters.Zusätzlicher Hinweis zum Lesen
quelle
3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope
nicht übereinstimmen würde. Einfacher zugrep -q docker /proc/1/cgroup
; Der Ergebniscode daraus sollte ebenfalls ausreichen.read
könnte funktionieren fürbash
, aber in der am häufigsten verwendetendash
Shell müssen Sie entwederread dummy
(oder ähnlich) oder ein Konstrukt wie[ -n "$(command)" ]
read
ohne Variablennamen unterstützt. Dies gilt nur für bash und ksh93. Die Opengroup gibt nur Verhalten ohne mindestens eine Variable anread var
und erwähnt es nichtread
. Wenn in bash und ksh93 kein var angegeben ist, verwendet read die Shell-VariableREPLY
.awk -F: '$3 ~ /docker/' /proc/self/cgroup | read
? Funktioniert bei mir.Was für mich funktioniert, ist die Überprüfung der Inode-Nummer des '/.' Im Docker ist es eine sehr hohe Zahl. Außerhalb des Dockers ist es eine sehr niedrige Zahl wie '2'. Ich gehe davon aus, dass dieser Ansatz auch vom verwendeten Dateisystem abhängt.
Beispiel
Im Hafen:
# ls -ali / | sed '2!d' |awk {'print $1'} 1565265
Vor dem Hafenarbeiter
$ ls -ali / | sed '2!d' |awk {'print $1'} 2
In einem Skript:
#!/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
quelle
ls -di /
? scheint inode num auf verschiedenen plattformen nicht zuverlässig zu seinWir mussten Prozesse ausschließen, die in Containern ausgeführt wurden, aber anstatt nur nach Docker-Gruppen zu suchen, haben wir uns entschlossen,
/proc/<pid>/ns/pid
mit dem Init-System unter zu vergleichen/proc/1/ns/pid
. Beispiel: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
Oder in unserem Fall wollten wir einen Einzeiler, der einen Fehler generiert, wenn sich der Prozess NICHT in einem Container befindet
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
Dies können wir von einem anderen Prozess aus ausführen. Wenn der Exit-Code Null ist, wird die angegebene PID in einem anderen Namespace ausgeführt.
quelle
readlink /proc/self/ns/pid
undreadlink /proc/1/ns/pid
erzeugt die gleiche Leistung.Basierend auf Dan Walshs Kommentar zur Verwendung von SELinux
ps -eZ | grep container_t
, ohne dassps
eine Installation erforderlich ist:Dies sagt Ihnen nur, dass Sie in einem Container laufen , aber nicht welche Laufzeit.
Andere Container-Laufzeiten wurden nicht überprüft, aber https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes bietet weitere Informationen und schlägt vor, dass dies weit verbreitet ist und möglicherweise auch für rkt und lxc funktioniert.
quelle
Golang-Code
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 }
quelle
Ich habe ein kleines Python-Skript erstellt. Hoffe, jemand findet es nützlich. :-)
#!/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)
quelle
FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'