Подтвердить что ты не робот

Как проверить, запущен ли процесс внутри контейнера докеров

[Обновлено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

4b9b3361

Ответ 1

Чтобы проверить внутри контейнера Docker, если вы находитесь внутри контейнера Docker, или нет, можно выполнить с помощью /proc/1/cgroup. Поскольку этот пост предлагает вам следующее:

За пределами контейнера докера все записи в /proc/1/cgroup заканчиваются на /, как вы можете видеть здесь:

[email protected]:~$ 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):

[email protected]:~$ 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:/

Ответ 2

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

Ответ 3

Мы используем расписание proc (/proc/$PID/sched) для извлечения PID процесса. Процесс PID внутри контейнера будет отличаться, чем PID на хосте (неконтейнерная система).

Например, вывод /proc/ 1/sched на контейнере вернется:

[email protected]:~# 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

Решение Томаса в качестве кода:

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

Примечание

read с фиктивной переменной - это простая идиома. Производит ли это какой-либо вывод?. Это компактный метод для поворота, возможно, подробного grep или awk, в тест шаблона.

Дополнительная заметка о чтении

Ответ 5

Нам нужно было исключить процессы, запущенные в контейнерах, но вместо того, чтобы проверять только докеры-группы, мы решили сравнить /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)"

который мы можем выполнить из другого процесса, и если код выхода равен нулю, указанный ПИД запускается в другом пространстве имен.