/kind feature
Description
What is the right way to detect if a process is running inside OCI or podman container? Multiply ways to detect that a process is running in docker container were suggested, including inspecting /proc/1/cgroup. As I don't really understand the contents of /proc/1/cgroup I can not be sure it will work cross-platform.
On Fedora 30 from podman.
~ podman run -it yakshaveinc/snapcraft:core18-edge cat /proc/1/cgroup
11:memory:/user.slice/user-1000.slice/session-3.scope
10:cpu,cpuacct:/
9:devices:/user.slice
8:hugetlb:/
7:pids:/user.slice/user-1000.slice/session-3.scope
6:perf_event:/
5:net_cls,net_prio:/
4:blkio:/
3:cpuset:/
2:freezer:/
1:name=systemd:/user.slice/user-1000.slice/session-3.scope
0::/user.slice/user-1000.slice/session-3.scope
Without podman.
~ cat /proc/1/cgroup
11:memory:/init.scope
10:cpu,cpuacct:/
9:devices:/init.scope
8:hugetlb:/
7:pids:/init.scope
6:perf_event:/
5:net_cls,net_prio:/
4:blkio:/
3:cpuset:/
2:freezer:/
1:name=systemd:/init.scope
0::/init.scope
Output of podman version:
Version: 1.4.4
RemoteAPI Version: 1
Go Version: go1.12.6
OS/Arch: linux/amd64
One pragmatic way is to check the mount point for /, e.g. by checking the content of /proc/PID/mounts. If it refers to a rootfs inside /var/lib/containers/storage, then it should be a podman container.
E.g.:
$ cat /proc/29839/mounts| grep -w "/"
/dev/sda3 / btrfs rw,relatime,ssd,space_cache,subvolid=24283,subvol=/@/var/lib/containers/storage/btrfs/subvolumes/de3c075de092df2e78eb5c3fd88c942d811cea1de18d86a6fdb4a08a967bfe8b 0
If you need to find out what's the podman container ID, you may need to search for that rootfs path in the runtime. E.g. if you think the OCI runtime is runc:
$ sudo grep -r -l de3c075de /run/runc
/run/runc/362fe56af3e003a487f8d9603540703d3713012f48c89d671c48acdf56c13848/state.json
Once you got the ID, you can inspect it with podman:
$ sudo podman inspect 362fe56af3e003a487f8d9603540703d3713012f48c89d671c48acdf56c13848
````
Or the OCI runtime itself:
$ sudo runc state 362fe56af3e003a487f8d9603540703d3713012f48c89d671c48acdf56c13848
```
I use SELinux to check.
ps -eZ | grep container_t
Tells me processes running in a container, but this does not tell you which container engine launched the container process.
grep container=podman /proc/12642/environ
Binary file /proc/12642/environ matches
Assuming we know the PID on the host, we can make a quick lookup via Podman:
[~]$ podman ps -a --format "{{.ID}}" | while read -a LINE; do podman top $LINE hpid; done | grep -v HPID
25094
25045
24996
24947
24895
24843
The command above prints a list of PIDs of container processes in the host's PID NS.
From inside container I haven't found references to /var/lib/containers from /proc/self/mounts. But I found /run/.containerenv documented at https://github.com/containers/libpod/blob/master/docs/podman-run.1.md as an official flag to detect that a program is in a container. Thanks for the pointers.
✗ podman run -it -v $PWD:/src:Z -w /src yakshaveinc/snapcraft:core18 cat /proc/self/mounts | grep container
tmpfs /dev tmpfs rw,context="system_u:object_r:container_file_t:s0:c317,c958",nosuid,size=65536k,mode=755,uid=1000,gid=1000 0 0
devpts /dev/pts devpts rw,context="system_u:object_r:container_file_t:s0:c317,c958",nosuid,noexec,relatime,gid=100004,mode=620,ptmxmode=666 0 0
shm /dev/shm tmpfs rw,context="system_u:object_r:container_file_t:s0:c317,c958",nosuid,nodev,noexec,relatime,size=64000k,uid=1000,gid=1000 0 0
tmpfs /run/.containerenv tmpfs rw,seclabel,nosuid,nodev,relatime,size=786412k,mode=700,uid=1000,gid=1000 0 0
tmpfs /sys/fs/cgroup tmpfs ro,context="system_u:object_r:container_file_t:s0:c317,c958",nosuid,nodev,noexec,relatime,mode=755,uid=1000,gid=1000 0 0
devpts /dev/console devpts rw,context="system_u:object_r:container_file_t:s0:c317,c958",nosuid,noexec,relatime,gid=100004,mode=620,ptmxmode=666 0 0
tmpfs /proc/acpi tmpfs ro,context="system_u:object_r:container_file_t:s0:c317,c958",relatime,uid=1000,gid=1000 0 0
tmpfs /proc/scsi tmpfs ro,context="system_u:object_r:container_file_t:s0:c317,c958",relatime,uid=1000,gid=1000 0 0
tmpfs /sys/firmware tmpfs ro,context="system_u:object_r:container_file_t:s0:c317,c958",relatime,uid=1000,gid=1000 0 0
tmpfs /sys/fs/selinux tmpfs ro,context="system_u:object_r:container_file_t:s0:c317,c958",relatime,uid=1000,gid=1000 0 0
grep container=podman /proc/12642/environ
I see $container set to oci, not podman. podman version 1.7.0.
EDIT: this was on a fedora:31 image
This can be overridden by images, podman run --env, etc
I'm fairly certain that we don't set oci explicitly anywhere in Podman itself.
(Unfortunately, this does mean that it's difficult to rely on the environment variable being set to any specific value - images in particular can override us)
Correct, container=oci, is being set by some Red Hat images, I believe.
Bottom line is checking if container is set, should be valid for thinking you are running inside of a container. What it is set to can vary..
As it was mentioned on https://github.com/cockpit-project/cockpit-container/issues/20 : Merely testing that $container is non-empty or oci is wrong for detecting podman. Docker on RHEL 7 sets container=oci.
We make a guarantee that the container environment variable will be set inside of a Podman container, and that if not overridden by the container or user it will be set to podman. Red Hat images happen to override by default, which is somewhat annoying.
The best check for container=oci being Docker or Podman would be to look for /run/.containerenv (Podman) vs /run/.dockerenv (Docker)
Most helpful comment
From inside container I haven't found references to
/var/lib/containersfrom/proc/self/mounts. But I found/run/.containerenvdocumented at https://github.com/containers/libpod/blob/master/docs/podman-run.1.md as an official flag to detect that a program is in a container. Thanks for the pointers.