Как проверить, запущен ли процесс внутри контейнера докеров
[Обновлено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
Ответы
Ответ 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)"
который мы можем выполнить из другого процесса, и если код выхода равен нулю, указанный ПИД запускается в другом пространстве имен.