[Actualizado1] Tengo un shell que cambiará los parámetros del kernel de TCP en algunas funciones, pero ahora necesito hacer que este shell se ejecute en el contenedor Docker, es decir, el shell necesita saber que se está ejecutando dentro de un contenedor y dejar de configurar el kernel.
Ahora no estoy seguro de cómo lograr eso, aquí está el contenido del /proc/self/cgroup
interior del contenedor:
9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
¿Puedo usar alguna de las banderas anteriores para averiguar si este proceso se está ejecutando dentro de un contenedor?
[Actualizado2]: También he notado Determinar si un proceso se ejecuta dentro de lxc / Docker , pero parece no funcionar en este caso, el contenido /proc/1/cgroup
de mi contenedor es:
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
No / lxc / containerid
shell
docker
containers
Harryz
fuente
fuente
Respuestas:
Para verificar dentro de un contenedor Docker si está dentro de un contenedor Docker o no, se puede hacer a través de
/proc/1/cgroup
. Como sugiere esta publicación , puede hacer lo siguiente:Fuera de un contenedor docker, todas las entradas
/proc/1/cgroup
terminan/
como puede ver aquí:Dentro de un contenedor Docker, algunos de los grupos de control pertenecerán a Docker (o LXC):
fuente
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 crea
.dockerenv
y( eliminados en v1.11 ) archivos en la parte superior del árbol de directorios del contenedor, por lo que es posible que desee verificar si existen..dockerinit
Algo como esto debería funcionar.
#!/bin/bash if [ -f /.dockerenv ]; then echo "I'm inside matrix ;("; else echo "I'm living in real world!"; fi
fuente
/.dockerinit
en su host (quizás por accidente), en cuyo caso será incorrecto fuera de un contenedor./.dockerenv
en el largo plazo. No está diseñado para usarse de esta manera ./.dockerenv
. Crea,/run/.containerenv
pero con una lógica similar, suena como un detalle de implementación en el que no se debe confiar. Consulte github.com/containers/libpod/issues/3586 para conocer algunas alternativas específicas de podman.La solución de Thomas como código:
running_in_docker() { (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input) }
Nota
El
read
con una variable ficticia es un modismo simple para ¿Produce esto alguna salida? . Es un método compacto para convertir un patrón posiblemente detalladogrep
oawk
en una prueba de un patrón.Nota adicional sobre lectura
fuente
3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope
no coincidiría. Más simple degrep -q docker /proc/1/cgroup
; el código de resultado de eso también debería ser suficiente.read
podría funcionarbash
, pero en eldash
shell más utilizado debe usarread dummy
(o similar) o usar una construcción como[ -n "$(command)" ]
read
sin nombre de variable. Esto solo es cierto para bash y ksh93. El Opengroup solo especificaread var
y no menciona elread
comportamiento sin al menos una variable. En bash y ksh93 , si no se proporciona var , read usa la variable de shellREPLY
.awk -F: '$3 ~ /docker/' /proc/self/cgroup | read
? Funciona para mi.Usamos el sched de proc (/ proc / $ PID / sched) para extraer el PID del proceso. El PID del proceso dentro del contenedor será diferente a su 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 es un contenedor:
$ cat /proc/1/sched | head -n 1 init (1, #threads: 1)
Esto ayuda a diferenciar si estás en un contenedor o no. por ejemplo, puedes hacer:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then { echo in docker } else { echo not in docker } fi
fuente
head -n1 /proc/1/sched
devuelvedumb-init (1, #threads: 1)
, por lo que la verificación sugerida en esta respuesta falla. (Además, contrariamente a lo que sugiere la respuesta, el PID se muestra como "1" en esa línea, aunque estoy haciendo esto en un contenedor).docker run --init ...
lo serádocker-init
. Si lo hace, por ejemplo,docker run ... head -n 1 /proc/1/sched
lo seráhead
.Lo que me funciona es comprobar el número de inodo del '/.' Dentro de la ventana acoplable, es un número muy alto. Fuera de la ventana acoplable, es un número muy bajo como '2'. Creo que este enfoque también dependería del FileSystem que se esté utilizando.
Ejemplo
Dentro de la ventana acoplable:
# ls -ali / | sed '2!d' |awk {'print $1'} 1565265
Fuera del acoplador
$ ls -ali / | sed '2!d' |awk {'print $1'} 2
En un guión:
#!/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
fuente
ls -di /
? Parece que el número de inodo no es confiable en una plataforma diferenteNecesitábamos excluir los procesos que se ejecutan en contenedores, pero en lugar de buscar solo docker cgroups, decidimos compararlos
/proc/<pid>/ns/pid
con el sistema init en/proc/1/ns/pid
. Ejemplo: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
O en nuestro caso queríamos un one liner que generara un error si el proceso NO está en un contenedor
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
que podemos ejecutar desde otro proceso y si el código de salida es cero, el PID especificado se está ejecutando en un espacio de nombres diferente.
fuente
readlink /proc/self/ns/pid
yreadlink /proc/1/ns/pid
producir el mismo resultado.Basado en el comentario de Dan Walsh sobre el uso de SELinux
ps -eZ | grep container_t
, pero sin necesidadps
de instalarlo:Esto solo le dice que está ejecutando en un contenedor, pero no en qué tiempo de ejecución.
No verifiqué otros tiempos de ejecución de contenedores, pero https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes proporciona más información y sugiere que esto se usa ampliamente, ¿ también podría funcionar para rkt y lxc?
fuente
He creado una pequeña secuencia de comandos de Python. Espero que alguien lo encuentre útil. :-)
#!/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)
fuente
FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'