[Обновлено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:/
Можно ли использовать любые указанные выше флаги, чтобы определить, выполняется ли этот процесс внутри контейнера?
[Обновлено2]: Я также заметил, что определение того, выполняется ли процесс внутри 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
shell
docker
containers
Гарриз
источник
источник
Ответы:
Чтобы проверить внутри контейнера Docker, находитесь ли вы внутри контейнера Docker или нет, можно сделать через
/proc/1/cgroup
. Как говорится в этом сообщении, вы можете сделать следующее:Вне контейнера докеров все записи
/proc/1/cgroup
заканчиваются,/
как вы можете видеть здесь:Внутри контейнера Docker некоторые группы управления будут принадлежать Docker (или LXC):
источник
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 создает файлы
.dockerenv
и( удаленные в v1.11 ) в верхней части дерева каталогов контейнера, поэтому вы можете проверить, существуют ли они..dockerinit
Примерно так должно работать.
#!/bin/bash if [ -f /.dockerenv ]; then echo "I'm inside matrix ;("; else echo "I'm living in real world!"; fi
источник
/.dockerinit
на вашем хосте (возможно, случайно), в этом случае это будет неправильно вне контейнера./.dockerenv
долгосрочную перспективу. Он не предназначен для использования таким образом ./.dockerenv
. Он действительно создает,/run/.containerenv
но по аналогичной логике звучит как детали реализации, на которые нельзя полагаться. См. Github.com/containers/libpod/issues/3586 для некоторых альтернатив, специфичных для podman.Мы используем расписание процесса (/ proc / $ PID / sched) для извлечения PID процесса. 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
источник
head -n1 /proc/1/sched
возвращаетсяdumb-init (1, #threads: 1)
, поэтому проверка, предложенная в этом ответе, не выполняется. (Кроме того, вопреки тому, что предполагает ответ, в этой строке PID отображается как «1», хотя я делаю это в контейнере.)docker run --init ...
это будетdocker-init
. Если вы это сделаете, например, такdocker run ... head -n 1 /proc/1/sched
и будетhead
.Решение Томаса в виде кода:
running_in_docker() { (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input) }
Запись
Параметр
read
с фиктивной переменной - это простая идиома для вывода? . Это компактный метод превращения, возможно, подробного текстаgrep
илиawk
в тест шаблона.Дополнительное примечание к прочтению
источник
3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope
не будет соответствовать. Прощеgrep -q docker /proc/1/cgroup
; код результата от этого также должен быть достаточным.read
может работатьbash
, но в наиболее часто используемойdash
оболочке вы должны использовать либоread dummy
(или аналогичный), либо конструкцию наподобие[ -n "$(command)" ]
read
без имени переменной. Это верно только для bash и ksh93. Opengroup только указываетread var
и не упоминаетread
поведение без хотя бы одной переменной. В баше и ksh93 , если не вар не задан, чтение использует переменные оболочкиREPLY
.awk -F: '$3 ~ /docker/' /proc/self/cgroup | read
? Работает на меня.Для меня работает проверка номера inode символа '/.' Внутри докера очень большое число. За пределами докера это очень маленькое число, например «2». Я считаю, что этот подход также будет зависеть от используемой файловой системы.
пример
Внутри докера:
# 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
источник
ls -di /
? кажется inode num ненадежным на другой платформеНам нужно было исключить процессы, запущенные в контейнерах, но вместо проверки только контрольных групп докеров мы решили сравнить
/proc/<pid>/ns/pid
с системой инициализации в/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 работает в другом пространстве имен.
источник
readlink /proc/self/ns/pid
иreadlink /proc/1/ns/pid
произвести тот же вывод.На основе комментария Дэна Уолша об использовании SELinux
ps -eZ | grep container_t
, но без необходимостиps
установки:Это просто говорит вам , что вы работаете в виде контейнера, но не которые во время выполнения.
Не проверял другие среды выполнения контейнеров, но https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes предоставляет дополнительную информацию и предполагает, что это широко используется, также может работать для rkt и lxc?
источник
код голанга
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 }
источник
Я создал небольшой скрипт на Python. Надеюсь, кто-то сочтет это полезным. :-)
#!/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)
источник
FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'