Есть ли способ определить, выполняется ли процесс (скрипт) внутри контейнера lxc (~ среда выполнения Docker)? Я знаю, что некоторые программы могут определить, работают ли они внутри виртуальной машины, доступно ли что-то подобное для lxc / docker?
Есть ли способ определить, выполняется ли процесс (скрипт) внутри контейнера lxc (~ среда выполнения Docker)? Я знаю, что некоторые программы могут определить, работают ли они внутри виртуальной машины, доступно ли что-то подобное для lxc / docker?
Ответы:
Самый надежный способ - это проверить /proc/1/cgroup
. Он скажет вам контрольные группы процесса инициализации, и когда вы не в контейнере, это будет /
для всех иерархий. Когда вы находитесь внутри контейнера, вы увидите название точки привязки. С контейнерами LXC / Docker это будет что-то вроде /lxc/<containerid>
или /docker/<containerid>
соответственно.
docker
вместо lxc
этих путей
/
для всех cgroups; в моей системе Debian 9 (systemd 232) только три из десяти cgroups ( 3:cpuset
, 4:perf_event
и 7:freezer
) находятся в корне; остальные находятся под /init.scope
. Тем не менее, я думаю, что поиск этого файла, :/docker/
возможно, является наиболее надежной эвристикой на данный момент.
grep 'docker\|lxc' /proc/1/cgroup
у меня работает на Docker 18.09.
Docker создает .dockerenv
файл в корне дерева каталогов внутри контейнера. Вы можете запустить этот скрипт для проверки
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
Еще:
Ubuntu на самом деле имеет скрипт bash: /bin/running-in-container
и он может возвращать тип контейнера, в котором он был вызван. Может быть полезным. Не знаю о других крупных дистрибутивах.
.dockerinit
файл был удален в последних версиях Docker , поэтому этот метод больше не будет работать. На момент написания, .dockerenv
файл все еще хранится, так что, возможно, его можно будет использовать вместо этого.
/bin/running-in-container
предоставляется upstart
. С переходом на systemd это может уйти. Я надеюсь, что нет - это звучит полезно!
.dockerenv
является не рекомендуется
В новой системе Ubuntu 16.04, новом systemd & lxc 2.0
sudo grep -qa container=lxc /proc/1/environ
Удобная функция Python для проверки работы в Docker:
def in_docker():
""" Returns: True if running in a Docker container, else False """
with open('/proc/1/cgroup', 'rt') as ifh:
return 'docker' in ifh.read()
kubepods
я думаю.
Мы используем схему процесса (/ 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)
Это помогает отличить, если вы находитесь в контейнере или нет.
sh
и не init
там, но это может быть почти что-либо в любом.
bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
Самый простой способ - проверить окружающую среду. Если у вас есть container=lxc
переменная, вы находитесь в контейнере.
В противном случае, если вы являетесь пользователем root, вы можете попытаться выполнить mknod
или выполнить mount
операцию, если она не удастся, вы, скорее всего, окажетесь в контейнере с удаленными возможностями.
/proc/1/cgroup
вы не можете это обнаружить.
docker run alpine env
не дает ничего похожего на эту переменную
Мой ответ применим только к процессам Node.js, но может быть актуален для некоторых посетителей, которые сталкиваются с этим вопросом и ищут конкретный ответ Node.js.
У меня была та же проблема, и я полагался на то, /proc/self/cgroup
что создал пакет npm исключительно для этой цели - чтобы определить, выполняется ли процесс Node.js внутри контейнера Docker или нет.
Контейнерный модуль НПМ поможет вам в Node.js. В настоящее время он не тестируется в Io.js, но может также работать и там.
Проверьте все решения выше в Python:
import os
def in_container():
proc_1 = r'/proc/1/sched'
if os.path.exists(proc_1):
with open(proc_1, 'r') as fp:
out = fp.read()
else:
out = ''
checks = [
'docker' in out,
'/lxc/' in out,
out.split(' ')[0] not in ('systemd', 'init',),
os.path.exists('./dockerenv'),
os.path.exists('/.dockerinit'),
os.getenv('container') is not None
]
return any(checks)
if __name__ == '__main__':
print(in_container())
Подтверждение концепции:
$ docker run --rm -it --mount type=bind,source=${PWD}/incontainer.py,target=/tmp/script.py python:3 python /tmp/script.py
True
def is_non_docker(): return os.path.exists('/proc/1/cgroup')
согласно принятому ответу здесь stackoverflow.com/questions/20010199/…
cat
! Хороший :-D
Докер развивается день ото дня, поэтому мы не можем точно сказать, собираются ли они остаться .dockerenv .dockerinit
в будущем.
В большинстве версий Linux init
это первый процесс для запуска. Но в случае контейнеров это не так.
#!/bin/bash
if ps -p1|grep -q init;then
echo "non-docker"
else
echo "docker"
fi
init
, который не соответствует действительности systemd
или launchd
систем на основе ...
init
хотя эти два и некоторые другие могут называть их PID 1 ), OpenRC, initng, runit. Смотрите здесь . Большинство современных систем на основе Linux будет использовать systemd
, некоторые старые, выскочки .... Все современные системы OS X будут использоватьlaunchd
Это SO Q & A: «Узнайте, работает ли ОС в виртуальной среде» ; хотя это не то же самое, что вопрос ОП, он действительно отвечает на распространенные случаи определения того, в каком контейнере вы находитесь (если вообще).
В частности, установите и прочитайте код этого bash-скрипта, который, кажется, работает довольно хорошо:
вирт-что :
sudo apt install virt-what
virt-what
версией 1.14-1 в Ubuntu 16.04. Нужен патч.
Я перевел ответ JJC на рубин
def in_docker
File.open('/proc/1/cgroup', 'rt') do |f|
contents = f.read
return contents =~ /docker/i || contents =~ /kubepod/i
end
rescue StandardError => e
p 'Local development'
p e
false
end
В Docker-контейнере записи /proc/self/cgroup
монтируются в cgroups на хосте.
например, в контейнере
# awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/docker/22bd0c154fb4e0d1b6c748faf1f1a12116acc21ce287618a115ad2bea41256b3
тогда как на хосте тоже самое
$ awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/
Использование чего-то в оболочке для низкопрофильного теста
is_running_in_container() {
awk -F: '/cpuset/ && $3 ~ /^\/$/{ c=1 } END { exit c }' /proc/self/cgroup
}
if is_running_in_container; then
echo "Aye!! I'm in a container"
else
echo "Nay!! I'm not in a container"
fi
Может быть, это сделать трюк:
if [ -z $(docker ps -q) ]; then
echo "There is not process currently running"
else
echo "There are processes running"
fi
Это то, что вы хотите? Надеюсь, это поможет =)
docker
двоичная доступен с внутренней стороны контейнера, очевидно.
docker
доступ к сокету docker хоста.