¿Hay alguna manera de determinar si un proceso (script) se ejecuta dentro de un contenedor lxc (~ Docker runtime)? Sé que algunos programas pueden detectar si se ejecutan dentro de una máquina virtual, ¿hay algo similar disponible para lxc / docker?
¿Hay alguna manera de determinar si un proceso (script) se ejecuta dentro de un contenedor lxc (~ Docker runtime)? Sé que algunos programas pueden detectar si se ejecutan dentro de una máquina virtual, ¿hay algo similar disponible para lxc / docker?
Respuestas:
La forma más confiable es verificar /proc/1/cgroup
. Se le dirá que los grupos de control del proceso init, y cuando estás no en un contenedor, que será /
para todas las jerarquías. Cuando esté dentro de un contenedor, verá el nombre del punto de anclaje. Con los contenedores LXC / Docker, será algo así /lxc/<containerid>
o /docker/<containerid>
respectivamente.
docker
lugar de lxc
en esos caminos
/
para todos los cgroups; en mi sistema Debian 9 (systemd 232) solo tres de los diez grupos c ( 3:cpuset
, 4:perf_event
y 7:freezer
) están en la raíz; El resto está debajo /init.scope
. Dicho esto, creo que buscar ese archivo :/docker/
es probablemente la heurística más confiable en este momento.
grep 'docker\|lxc' /proc/1/cgroup
funciona para mí en Docker 18.09.
Docker crea un .dockerenv
archivo en la raíz del árbol de directorios dentro del contenedor. Puede ejecutar este script para verificar
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
MÁS:
Ubuntu en realidad tiene un script bash: /bin/running-in-container
y en realidad puede devolver el tipo de contenedor en el que se ha invocado. Podría ser útil. Sin embargo, no sé sobre otras distribuciones importantes.
.dockerinit
archivo se ha eliminado en versiones recientes de Docker , por lo que este método ya no funcionará. Al momento de escribir esto, el .dockerenv
archivo todavía se mantiene, por lo que quizás podría usarse en su lugar.
/bin/running-in-container
es proporcionado por upstart
. Con la transición a systemd, podría desaparecer. Espero que no, ¡suena útil!
.dockerenv
se no se recomienda
En un nuevo sistema ubuntu 16.04, nuevo systemd y lxc 2.0
sudo grep -qa container=lxc /proc/1/environ
Práctica función de Python para verificar si se ejecuta en 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
supongo.
Usamos el programado del proceso (/ proc / $ PID / sched) para extraer el PID del proceso. El PID del proceso dentro del contenedor será diferente, entonces es PID en el host (un sistema sin contenedor).
Por ejemplo, la salida de / proc / 1 / sched en un contenedor devolverá:
root@33044d65037c:~# cat /proc/1/sched | head -n 1
bash (5276, #threads: 1)
Mientras esté en un host que no sea contenedor:
$ cat /proc/1/sched | head -n 1
init (1, #threads: 1)
Esto ayuda a diferenciar si estás en un contenedor o no.
sh
y no está init
allí, pero puede ser casi cualquier cosa.
bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
La forma más fácil sería verificar el entorno. Si tiene la container=lxc
variable, está dentro de un contenedor.
De lo contrario, si es root, puede intentar realizar mknod
u mount
operar, si falla, lo más probable es que se encuentre en un contenedor con capacidades caídas.
/proc/1/cgroup
no le permite detectar eso.
docker run alpine env
no da nada que se parezca a esa variable
Mi respuesta solo se aplica a los procesos Node.js pero puede ser relevante para algunos visitantes que tropiezan con esta pregunta en busca de una respuesta específica de Node.js.
Tuve el mismo problema y confiando en /proc/self/cgroup
que creé un paquete npm solo para este propósito: detectar si un proceso Node.js se ejecuta dentro de un contenedor Docker o no.
El módulo npm contenedorizado lo ayudará en Node.js. Actualmente no está probado en Io.js, pero también podría funcionar allí.
Verifique todas las soluciones anteriores en 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())
Prueba de concepto:
$ 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')
según la respuesta aceptada aquí stackoverflow.com/questions/20010199/…
cat
! Nice one :-D
Docker está evolucionando día a día, por lo que no podemos decir con certeza si se mantendrán .dockerenv .dockerinit
en el futuro.
En la mayoría de los sabores de Linux init
es el primer proceso en comenzar. Pero en el caso de los contenedores esto no es cierto.
#!/bin/bash
if ps -p1|grep -q init;then
echo "non-docker"
else
echo "docker"
fi
init
, que no es cierto en systemd
o launchd
sistemas basados ...
init
), OpenRC, initng, runit. Vea aquí . La mayoría de los sistemas modernos basados en Linux usarían systemd
, algunos más antiguos, nuevos ... Todos los sistemas OS X modernos usaríanlaunchd
Estas preguntas y respuestas sobre SO: "Averigüe si el sistema operativo se ejecuta en un entorno virtual" ; aunque no es lo mismo que la pregunta del OP, de hecho responde a casos comunes de encontrar en qué contenedor se encuentra (si es que lo hace).
En particular, instale y lea el código de este script bash que parece funcionar bastante bien:
virt-what :
sudo apt install virt-what
virt-what
versión 1.14-1 en Ubuntu 16.04. Necesita parche.
He traducido la respuesta de JJC al rubí
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
En un contenedor acoplable, las entradas /proc/self/cgroup
se montan en cgroups en el host.
por ejemplo, en un contenedor
# awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/docker/22bd0c154fb4e0d1b6c748faf1f1a12116acc21ce287618a115ad2bea41256b3
mientras que, lo mismo en el host
$ awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/
Usar algo en el shell para una prueba de bajo perfil
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
Tal vez esto haga el truco:
if [ -z $(docker ps -q) ]; then
echo "There is not process currently running"
else
echo "There are processes running"
fi
¿Es eso lo que quieres? Espero que ayude =)
docker
binarios disponibles desde el interior del contenedor, obviamente.
docker
acceso al zócalo docker de los hosts.