[Atualizado1] Eu tenho um shell que mudará os parâmetros do kernel TCP em algumas funções, mas agora preciso fazer esse shell rodar no contêiner Docker, ou seja, o shell precisa saber que está rodando dentro de um contêiner e parar de configurar o kernel.
Agora não tenho certeza de como fazer isso, aqui está o conteúdo de /proc/self/cgroup
dentro do contêiner:
9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Posso usar algum sinalizador acima para descobrir se esse processo está sendo executado dentro de um contêiner?
[Atualizado2]: também observei como determinar se um processo é executado dentro do lxc / Docker , mas parece não funcionar neste caso, o conteúdo /proc/1/cgroup
do meu contêiner é:
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Não / lxc / containerid
shell
docker
containers
harryz
fonte
fonte
Respostas:
Para verificar dentro de um contêiner Docker se você está dentro de um contêiner Docker ou não, pode ser feito através de
/proc/1/cgroup
. Como esta postagem sugere, você pode fazer o seguinte:Fora de um contêiner docker, todas as entradas
/proc/1/cgroup
terminam,/
como você pode ver aqui:Dentro de um contêiner do Docker, alguns dos grupos de controle pertencerão ao Docker (ou LXC):
fonte
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
O Docker cria
.dockerenv
e( remove na v1.11 ) arquivos no topo da árvore de diretórios do contêiner, então você pode querer verificar se eles existem..dockerinit
Algo assim deve funcionar.
#!/bin/bash if [ -f /.dockerenv ]; then echo "I'm inside matrix ;("; else echo "I'm living in real world!"; fi
fonte
/.dockerinit
em seu host (talvez por acidente), caso em que estará errado fora de um contêiner./.dockerenv
longo prazo. Não se destina a ser usado desta forma ./.dockerenv
. Ele cria,/run/.containerenv
mas por uma lógica semelhante, soa como detalhes de implementação nos quais não se pode confiar. Consulte github.com/containers/libpod/issues/3586 para algumas alternativas específicas do podman.Usamos o sched do proc (/ proc / $ PID / sched) para extrair o PID do processo. O PID do processo dentro do contêiner será diferente do PID no host (um sistema não contêiner).
Por exemplo, a saída de / proc / 1 / sched em um contêiner retornará:
root@33044d65037c:~# cat /proc/1/sched | head -n 1 bash (5276, #threads: 1)
Enquanto em um host não contêiner:
$ cat /proc/1/sched | head -n 1 init (1, #threads: 1)
Isso ajuda a diferenciar se você está em um contêiner ou não. por exemplo, você pode fazer:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then { echo in docker } else { echo not in docker } fi
fonte
head -n1 /proc/1/sched
retornadumb-init (1, #threads: 1)
, portanto, a verificação sugerida nesta resposta falha. (Além disso, ao contrário do que a resposta sugere, o PID é mostrado como "1" nessa linha, embora eu esteja fazendo isso em um contêiner.)docker run --init ...
isso, serádocker-init
. Se você fizerdocker run ... head -n 1 /proc/1/sched
isso, por exemplo , seráhead
.A solução de Thomas como código:
running_in_docker() { (awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input) }
Nota
O
read
com uma variável fictícia é um idioma simples para Isso produz alguma saída? . É um método compacto para transformar um possivelmente prolixogrep
ouawk
um teste de um padrão.Nota adicional na leitura
fonte
3:cpu,cpuacct:/system.slice/docker-1ce79a0dec4a2084d54acf187a1e177e0339dc90d0218b48b4456576ecaf291e.scope
não corresponderia. Mais simples paragrep -q docker /proc/1/cgroup
; o código de resultado disso também deve ser suficiente.read
pode funcionar parabash
, mas nodash
shell mais usado você tem que usarread dummy
(ou semelhante) ou usar uma construção como[ -n "$(command)" ]
read
nome simples sem variável. Isso só é verdade para bash e ksh93. O Opengroup apenas especificaread var
e não menciona oread
comportamento sem pelo menos uma variável. Em bash e ksh93 , se nenhuma var for fornecida, read usa a variável shellREPLY
.awk -F: '$3 ~ /docker/' /proc/self/cgroup | read
? Funciona para mim.O que funciona para mim é verificar o número do inode do '/.' Dentro da janela de encaixe, é um número muito alto. Fora do docker, é um número muito baixo, como '2'. Acho que essa abordagem também dependeria do FileSystem sendo usado.
Exemplo
Dentro da janela de encaixe:
# ls -ali / | sed '2!d' |awk {'print $1'} 1565265
Fora do docker
$ ls -ali / | sed '2!d' |awk {'print $1'} 2
Em um script:
#!/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
fonte
ls -di /
? parece inode num não confiável em plataforma diferentePrecisamos excluir processos em execução em contêineres, mas em vez de verificar apenas os cgroups do docker, decidimos comparar
/proc/<pid>/ns/pid
com o sistema init em/proc/1/ns/pid
. Exemplo: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
Ou, em nosso caso, queríamos um liner que gerasse um erro se o processo NÃO estivesse em um contêiner
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
que podemos executar a partir de outro processo e se o código de saída for zero, o PID especificado está sendo executado em um namespace diferente.
fonte
readlink /proc/self/ns/pid
ereadlink /proc/1/ns/pid
produza a mesma saída.Com base no comentário de Dan Walsh sobre o uso do SELinux
ps -eZ | grep container_t
, mas sem a necessidadeps
de instalação:Isso apenas informa que você está executando em um contêiner, mas não em qual tempo de execução.
Não verificou outros tempos de execução do contêiner, mas https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes fornece mais informações e sugere que isso é amplamente usado, também pode funcionar para rkt e lxc?
fonte
código golang
func GetContainerID(pid int32) string { cgroupPath := fmt.Sprintf("/proc/%s/cgroup", strconv.Itoa(int(pid))) return getContainerID(cgroupPath) } func GetImage(containerId string) string { if containerId == "" { return "" } image, ok := containerImage[containerId] if ok { return image } else { return "" } } func getContainerID(cgroupPath string) string { containerID := "" content, err := ioutil.ReadFile(cgroupPath) if err != nil { return containerID } lines := strings.Split(string(content), "\n") for _, line := range lines { field := strings.Split(line, ":") if len(field) < 3 { continue } cgroup_path := field[2] if len(cgroup_path) < 64 { continue } // Non-systemd Docker //5:net_prio,net_cls:/docker/de630f22746b9c06c412858f26ca286c6cdfed086d3b302998aa403d9dcedc42 //3:net_cls:/kubepods/burstable/pod5f399c1a-f9fc-11e8-bf65-246e9659ebfc/9170559b8aadd07d99978d9460cf8d1c71552f3c64fefc7e9906ab3fb7e18f69 pos := strings.LastIndex(cgroup_path, "/") if pos > 0 { id_len := len(cgroup_path) - pos - 1 if id_len == 64 { //p.InDocker = true // docker id containerID = cgroup_path[pos+1 : pos+1+64] // logs.Debug("pid:%v in docker id:%v", pid, id) return containerID } } // systemd Docker //5:net_cls:/system.slice/docker-afd862d2ed48ef5dc0ce8f1863e4475894e331098c9a512789233ca9ca06fc62.scope docker_str := "docker-" pos = strings.Index(cgroup_path, docker_str) if pos > 0 { pos_scope := strings.Index(cgroup_path, ".scope") id_len := pos_scope - pos - len(docker_str) if pos_scope > 0 && id_len == 64 { containerID = cgroup_path[pos+len(docker_str) : pos+len(docker_str)+64] return containerID } } } return containerID }
fonte
Eu criei um pequeno script python. Espero que alguém ache ú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)
fonte
FileNotFoundError: [Errno 2] No such file or directory: '/sys/fs/cgroup/memory/docker/<docker_id>/memory.stat'