[Zaktualizowano1] Mam powłokę, która zmieni parametry jądra TCP w niektórych funkcjach, ale teraz muszę uruchomić tę powłokę w kontenerze Dockera, co oznacza, że powłoka musi wiedzieć, że działa w kontenerze i przestać konfigurować jądro.
Teraz nie jestem pewien, jak to osiągnąć, oto zawartość /proc/self/cgroup
wnętrza pojemnika:
9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Jakiekolwiek flagi powyżej, których mogę użyć, aby dowiedzieć się, czy ten proces działa w kontenerze?
[Zaktualizowano2]: Zauważyłem również, że ustalanie, czy proces działa w lxc / Docker , ale wydaje się nie działać w tym przypadku, zawartość /proc/1/cgroup
mojego kontenera to:
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
No / lxc / containerid
shell
docker
containers
harryz
źródło
źródło
Odpowiedzi:
Aby sprawdzić wewnątrz kontenera Docker, czy jesteś w kontenerze Docker, czy nie, można to zrobić za pomocą
/proc/1/cgroup
. Jak sugeruje ten post , możesz wykonać następujące czynności:Poza kontenerem docker wszystkie wpisy
/proc/1/cgroup
kończą się,/
jak widać tutaj:Wewnątrz kontenera Docker niektóre grupy kontrolne będą należeć do Dockera (lub LXC):
źródło
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 tworzy
.dockerenv
i( usunięte w wersji 1.11 ) pliki na górze drzewa katalogów kontenera, więc możesz chcieć sprawdzić, czy one istnieją..dockerinit
Coś takiego powinno działać.
#!/bin/bash if [ -f /.dockerenv ]; then echo "I'm inside matrix ;("; else echo "I'm living in real world!"; fi
źródło
/.dockerinit
na twoim hoście (być może przez przypadek), w takim przypadku będzie źle poza kontenerem./.dockerenv
dłuższą metę. Nie jest przeznaczone do tego celu ./.dockerenv
. Tworzy,/run/.containerenv
ale zgodnie z podobną logiką brzmi jak szczegół implementacji, na którym nie można polegać. Zobacz github.com/containers/libpod/issues/3586, aby zapoznać się z alternatywami specyficznymi dla podmana.Używamy harmonogramu proc (/ proc / $ PID / schedule), aby wyodrębnić PID procesu. PID procesu wewnątrz kontenera będzie się różnił od jego PID na hoście (system niekontenerowy).
Na przykład wynik polecenia / proc / 1 / schedule w kontenerze zwróci:
root@33044d65037c:~# cat /proc/1/sched | head -n 1 bash (5276, #threads: 1)
Na hoście innym niż kontener:
$ cat /proc/1/sched | head -n 1 init (1, #threads: 1)
Pomaga to w rozróżnieniu, czy jesteś w kontenerze, czy nie. np. możesz zrobić:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then { echo in docker } else { echo not in docker } fi
źródło
head -n1 /proc/1/sched
zwracadumb-init (1, #threads: 1)
, więc sprawdzenie sugerowane w tej odpowiedzi kończy się niepowodzeniem. (Ponadto, wbrew temu, co sugeruje odpowiedź, PID jest wyświetlany jako „1” w tym wierszu, chociaż robię to w kontenerze.)docker run --init ...
, będziedocker-init
. Jeśli to zrobisz,docker run ... head -n 1 /proc/1/sched
to będziehead
.Rozwiązanie Thomasa jako kod:
running_in_docker() { (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input) }
Uwaga
read
Ze zmienną manekina jest proste idiom za to się wyświetli niczego? . Jest to kompaktowa metoda przekształcania być może rozwlekłegogrep
lubawk
w test wzoru.Dodatkowa uwaga dotycząca czytania
źródło
3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope
Nie będzie pasować. Prostszegrep -q docker /proc/1/cgroup
; kod wynikowy z tego również powinien być wystarczający.read
może zadziałaćbash
, ale w najczęściej używanejdash
powłoce musisz użyć alboread dummy
(lub podobnego) lub użyć konstrukcji takiej jak[ -n "$(command)" ]
read
bez nazwy zmiennej. Dotyczy to tylko bash i ksh93. Grupa Opengroup określa tylkoread var
i nie wspomina oread
zachowaniu bez co najmniej jednej zmiennej. W bash i ksh93 , jeśli nie var jest podana, czytać używa zmiennej powłokiREPLY
.awk -F: '$3 ~ /docker/' /proc/self/cgroup | read
? Pracuje dla mnie.W moim przypadku działa sprawdzanie numeru i-węzła „/”. Wewnątrz dockera jest bardzo dużo. Poza dokerem jest to bardzo niska liczba, np. „2”. Sądzę, że to podejście zależałoby również od używanego systemu plików.
Przykład
Wewnątrz dokera:
# ls -ali / | sed '2!d' |awk {'print $1'} 1565265
Poza dokerem
$ ls -ali / | sed '2!d' |awk {'print $1'} 2
W skrypcie:
#!/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
źródło
ls -di /
? wydaje się, że numer i-węzła nie jest wiarygodny na innej platformieMusieliśmy wykluczyć procesy działające w kontenerach, ale zamiast sprawdzać tylko grupy cgroup Dockera, zdecydowaliśmy się porównać
/proc/<pid>/ns/pid
z systemem init pod adresem/proc/1/ns/pid
. Przykład: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
Lub w naszym przypadku chcieliśmy mieć jedną wkładkę, która generuje błąd, jeśli proces NIE jest w pojemniku
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
który możemy wykonać z innego procesu i jeśli kod zakończenia ma wartość zero, to określony PID działa w innej przestrzeni nazw.
źródło
readlink /proc/self/ns/pid
ireadlink /proc/1/ns/pid
dają ten sam wynik.Na podstawie komentarza Dana Walsha o używaniu SELinux
ps -eZ | grep container_t
, ale bez koniecznościps
instalacji:To właśnie mówi ci używasz w w pojemniku, ale nie które Runtime.
Nie sprawdzono innych środowisk wykonawczych kontenera, ale https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes zawiera więcej informacji i sugeruje, że jest to powszechnie używane, może również działać w przypadku rkt i lxc?
źródło
Stworzyłem mały skrypt w Pythonie. Mam nadzieję, że ktoś uzna to za przydatne. :-)
#!/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)
źródło
FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'