[Updated1] I have a shell which will change TCP kernel parameters in some functions, but now I need to make this shell run in Docker container, that means, the shell need to
Based on Dan Walsh's comment about using SELinux ps -eZ | grep container_t
, but without requiring ps
to be installed:
$ podman run --rm fedora:31 cat /proc/1/attr/current
system_u:system_r:container_t:s0:c56,c299
$ podman run --rm alpine cat /proc/1/attr/current
system_u:system_r:container_t:s0:c558,c813
$ docker run --rm fedora:31 cat /proc/1/attr/current
system_u:system_r:container_t:s0:c8,c583
$ cat /proc/1/attr/current
system_u:system_r:init_t:s0
This just tells you you're running in a container, but not which runtime.
Didn't check other container runtimes but https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes provides more info and suggests this is widely used, might also work for rkt and lxc?
To check inside a Docker container if you are inside a Docker container or not can be done via /proc/1/cgroup
. As this post suggests you can to the following:
Outside a docker container all entries in /proc/1/cgroup
end on /
as you can see here:
vagrant@ubuntu-13:~$ 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:/
Inside a Docker container some of the control groups will belong to Docker (or LXC):
vagrant@ubuntu-13:~$ 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:/
We needed to exclude processes running in containers, but instead of checking for just docker cgroups we decided to compare /proc/<pid>/ns/pid
to the init system at /proc/1/ns/pid
. Example:
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
Or in our case we wanted a one liner that generates an error if the process is NOT in a container
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
which we can execute from another process and if the exit code is zero then the specified PID is running in a different namespace.
I've created a small python script. Hope someone finds it useful. :-)
#!/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)
Docker creates .dockerenv
and (removed in v1.11) files at the top of the container's directory tree so you might want to check if those exist..dockerinit
Something like this should work.
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
We use the proc's sched (/proc/$PID/sched) to extract the PID of the process. The process's PID inside the container will differ then it's PID on the host (a non-container system).
For example, the output of /proc/1/sched on a container will return:
root@33044d65037c:~# cat /proc/1/sched | head -n 1
bash (5276, #threads: 1)
While on a non-container host:
$ cat /proc/1/sched | head -n 1
init (1, #threads: 1)
This helps to differentiate if you are in a container or not. eg you can do:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then {
echo in docker
} else {
echo not in docker
} fi