How to Determine If a Process Runs Inside Lxc/Docker

How to determine if a process runs inside lxc/Docker?

The most reliable way is to check /proc/1/cgroup. It will tell you the control groups of the init process, and when you are not in a container, that will be / for all hierarchies. When you are inside a container, you will see the name of the anchor point. With LXC/Docker containers, it will be something like /lxc/<containerid> or /docker/<containerid> respectively.

How to check if a process is running inside docker container?

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:/

How to detect if the current script is running in a docker build?

Try this :

#!/bin/bash

# myscript.sh

isDocker(){
local cgroup=/proc/1/cgroup
test -f $cgroup && [[ "$(<$cgroup)" = *:cpuset:/docker/* ]]
}

isDockerBuildkit(){
local cgroup=/proc/1/cgroup
test -f $cgroup && [[ "$(<$cgroup)" = *:cpuset:/docker/buildkit/* ]]
}

isDockerContainer(){
[ -e /.dockerenv ]
}

if isDockerBuildkit || (isDocker && ! isDockerContainer)
then
echo "I am in a docker build"
else
echo "I am not in a docker build"
fi

How to know a process is running under docker?

You can identify Docker process via the process tree on the Docker host (or on the VM if using docker for mac/windows)

The parent process to 2924(haproxy) is 2902

The parent process to 2902(haproxy-start) is 2881

2881 will be docker-container which is managed by a dockerd process

To view your process listing in a tree format use ps -ejH or pstree (available in the psmisc package)

To get a quick list of whats running under dockerd

/ # pstree $(pgrep dockerd)
dockerd-+-docker-containe-+-docker-containe-+-java---17*[{java}]
| | `-8*[{docker-containe}]
| |-docker-containe-+-sinopia-+-4*[{V8 WorkerThread}]
| | | |-{node}
| | | `-4*[{sinopia}]
| | `-8*[{docker-containe}]
| |-docker-containe-+-node-+-4*[{V8 WorkerThread}]
| | | `-{node}
| | `-8*[{docker-containe}]
| |-docker-containe-+-tinydns
| | `-8*[{docker-containe}]
| |-docker-containe-+-dnscache
| | `-8*[{docker-containe}]
| |-docker-containe-+-apt-cacher-ng
| | `-8*[{docker-containe}]
| `-20*[{docker-containe}]
|-2*[docker-proxy---6*[{docker-proxy}]]
|-docker-proxy---5*[{docker-proxy}]
|-2*[docker-proxy---4*[{docker-proxy}]]
|-docker-proxy---8*[{docker-proxy}]
`-28*[{dockerd}]

Show the parents of a PID (-s)

/ # pstree -aps 3744 
init,1
`-dockerd,1721 --pidfile=/run/docker.pid -H unix:///var/run/docker.sock --swarm-default-advertise-addr=eth0
`-docker-containe,1728 -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim ...
`-docker-containe,3711 8d923b3235eb963b735fda847b745d5629904ccef1245d4592cc986b3b9b384a...
`-java,3744 -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp/zookeeper/bin/../build/cl
|-{java},4174
|-{java},4175
|-{java},4176
|-{java},4177
|-{java},4190
|-{java},4208
|-{java},4209
|-{java},4327
|-{java},4328
|-{java},4329
|-{java},4330
|-{java},4390
|-{java},4416
|-{java},4617
|-{java},4625
|-{java},4629
`-{java},4632

Show all children of docker, including namespace changes (-S):

/ # pstree -apS $(pgrep dockerd) 
dockerd,1721 --pidfile=/run/docker.pid -H unix:///var/run/docker.sock --swarm-default-advertise-addr=eth0
|-docker-containe,1728 -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim ...
| |-docker-containe,3711 8d923b3235eb963b735fda847b745d5629904ccef1245d4592cc986b3b9b384a...
| | |-java,3744,ipc,mnt,net,pid,uts -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp/zookeeper/bin/../build/cl
| | | |-{java},4174
| | | |-{java},4175
| | | |-{java},4629
| | | `-{java},4632
| | |-{docker-containe},3712
| | `-{docker-containe},4152
| |-docker-containe,3806 49125f8274242a5ae244ffbca121f354c620355186875617d43876bcde619732...
| | |-sinopia,3841,ipc,mnt,net,pid,uts
| | | |-{V8 WorkerThread},4063
| | | |-{V8 WorkerThread},4064
| | | |-{V8 WorkerThread},4065
| | | |-{V8 WorkerThread},4066
| | | |-{node},4062
| | | |-{sinopia},4333
| | | |-{sinopia},4334
| | | |-{sinopia},4335
| | | `-{sinopia},4336
| | |-{docker-containe},3814
| | `-{docker-containe},4038
| |-docker-containe,3846 2a756d94c52d934ba729927b0354014f11da6319eff4d35880a30e72e033c05d...
| | |-node,3910,ipc,mnt,net,pid,uts lib/dnsd.js
| | | |-{V8 WorkerThread},4204
| | | |-{V8 WorkerThread},4205
| | | |-{V8 WorkerThread},4206
| | | |-{V8 WorkerThread},4207
| | | `-{node},4203

How does Java application know it is running within a Docker container

Solution

Check control group of the init process simply by /proc/1/cgroup .

  • if it is initiated normally all hierarchies have in / value
  • if it is initiated from docker container they have /docker/<container_id> value.

When running inside docker /proc/1/cgroup has values similar to :

11:perf_event:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
10:memory:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
9:cpuset:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
8:net_cls,net_prio:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
7:pids:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
6:cpu,cpuacct:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
5:blkio:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
4:freezer:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
3:hugetlb:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
2:devices:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249
1:name=systemd:/docker/897df2a033d6ab07c357c1ac1f75741bd16474487de83c6d4d98518e5ef52249

Note: As @JanisKirsteins informed me, If you run your application in amazon ec2 you might want to change the condition to line.contains("/ecs") instead. because in /proc/1/cgroups you will find pattern similar to: /ecs/<uuid>/<uuid>


In Java

public static Boolean isRunningInsideDocker() {

try (Stream < String > stream =
Files.lines(Paths.get("/proc/1/cgroup"))) {
return stream.anyMatch(line -> line.contains("/docker"));
} catch (IOException e) {
return false;
}
}

Live code checking


  • outside docker: running outside docker
  • inside docker : running inside docker

More Info

  • https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/
  • How to determine if a process runs inside lxc/Docker?
  • How to check if a process is running inside docker container

Detect if process executes inside a Windows Container

New readers can skip ahead to the part marked with "Update" which contains the accepted solution.

A quick check with whoami on the command prompt showed that the combination of domain and username that is used inside a container seems to be rather unusual. So I used this code to solve the problem:

function Test-IsInsideContainer {
if( ($env:UserName -eq "ContainerAdministrator") -and ($env:UserDomain -eq "User Manager") ) {
$true
}
else {
$false
}
}

Update: Another option is to check if the service cexecsvc exist. An internet search did not yield much information about this service, but its name (Container Execution Agent) suggests that it only exists inside of containers (which I verified with some quick test on Win10 and a Server2016 Docker-host).
So maybe this code meets your requirements (I am a newbie in Powershell):

function Test-IsInsideContainer {
$foundService = Get-Service -Name cexecsvc -ErrorAction SilentlyContinue
if( $foundService -eq $null ) {
$false
}
else {
$true
}
}


Related Topics



Leave a reply



Submit