Is there any way to determine if a process (script) runs inside an lxc container (~ Docker runtime)? I know that some programs are able to detect whether they run inside a virtual machine, is something similar available for lxc/docker?
-
It might seem pedantic, but it would be best to rephrase your question to describe a problem you're having and ask how to solve it -- without that, the question stands a higher chance of being closed. In many cases it's difficult to make that change but in yours it wouldn't be hard to simply rephrase if you wish. – mah Nov 15 '13 at 21:04
-
there is an interesting response when issuing this command while inside a container : uptime – Scott Stensland Feb 19 '17 at 01:16
19 Answers
Docker creates a .dockerenv
file at the root of the directory tree inside container. This can be seen by performing an ls -la /.dockerenv
to show that it is created on container startup.
You can run this script to verify:
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
MORE:
Ubuntu actually has a bash script: /bin/running-in-container
and it can return the type of container it has been invoked in. Might be helpful.
Don't know about other major distros though.

- 35,625
- 19
- 175
- 265

- 4,522
- 2
- 14
- 10
-
4On Debian `/bin/running-in-container` is provided by `upstart`. With the transition to systemd it might go away. I hope not - it sounds useful! – Max Murphy Sep 01 '16 at 09:12
-
"on top of directory tree", what does that mean? where is that? – Alexander Mills Dec 20 '16 at 10:18
-
9Others have pointed out that checking `.dockerenv` is [not recommended](https://github.com/moby/moby/issues/18355#issuecomment-220484748) – Dave Sep 25 '18 at 10:53
-
-
6Note: testing for .dockerenv works only if the runtime is docker daemon. If you are using podman or something else this fails. – Ben Kircher Sep 07 '19 at 10:13
-
2It's Aug 2020 and `/.dockerenv` is available on ubuntu:20.04 and alpine:3.12, so I'd say that's definitely the best answer – Meir Gabay Aug 06 '20 at 11:12
-
2
-
What if you want to run this from your script, which is inside WORKDIR? – The Onin Jul 22 '23 at 23:17
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.
-
14
-
6Does not work for lxd/lxc containers, but http://stackoverflow.com/a/20010626/170230 does. – Draco Ater Jun 08 '16 at 06:39
-
2With later versions of systemd it looks like you can't rely on process 1 using `/` for all cgroups; on my Debian 9 system (systemd 232) only three of the ten cgroups (`3:cpuset`, `4:perf_event` and `7:freezer`) are at root; the rest are under `/init.scope`. That said, I think that searching that file for `:/docker/` is probably the most reliable heuristic at the moment. – cjs Feb 28 '18 at 07:40
-
3
-
Here's a tighter (extended) regex that assumes a `sha256` hash in the `basename` position: `grep -Eq '/(lxc|docker)/[[:xdigit:]]{64}' /proc/1/cgroup` – rubicks Jun 14 '19 at 14:40
-
1Combining two answers for increased robustness: `if [[ -f /.dockerenv ]] || grep -Eq '(lxc|docker)' /proc/1/cgroup; then echo True; else echo False; fi` (Though I don't know if cgroup file is in every linux; You might whant to add extra checks) – Boop Jul 02 '19 at 14:25
-
4Not working for me. Host Ubuntu 19.04, guest Ubuntu 18.04 using LXC privileged container. /proc/1/cgroup does NOT contain the lxc string. – Gab Sep 01 '19 at 11:51
-
Not sure this is correct when using a schroot instead, in such case the cgroup is still the same – Treviño Jan 20 '21 at 13:22
-
Worth adding that the same way wouldn't work for detecting `chroot`, because if `/proc/` is mounted inside chroot the `cgroup` gonna have same content. There's a different way with `/proc`, but apparently no unified way to detect both chroot and docker at the same time. – Hi-Angel Aug 02 '21 at 13:54
-
10
-
1I'm running fedora 34 and the output of /proc/1/cgroup inside a container ir 0::/ If the linux distribuition relies on systemd a possible way is to check if the contents of /proc/1/comm are not 'systemd' – Henrique Capozzi Dec 11 '21 at 15:51
-
-
As [stated here](https://www.baeldung.com/linux/is-process-running-inside-container), you might also want to try: `cat /proc/self/mountinfo` If it works, that’s because it’s using control group v2, instead of v1 (which uses /proc/1/cgroup). – Andorkan Jul 15 '23 at 17:47
On a new ubuntu 16.04 system, new systemd & lxc 2.0
sudo grep -qa container=lxc /proc/1/environ

- 291
- 3
- 2
-
2This works for me on Ubuntu focal 20.04. None of the answers above this point did. – Jonathan Hartley Apr 23 '20 at 15:18
-
Thanks! it works for lxc! Can you please explain why '-a' is needed? Isn't `grep -q container=lxc /proc/1/environ` enough? – Alek Apr 28 '21 at 16:55
-
1`/proc/$$/environ` separates environment variables with null bytes. Without `-a`, this passage from the man page applies: > By default, TYPE is binary, and grep suppresses output after null input binary data is discovered – Adam Azarchs Sep 22 '21 at 20:56
-
For me, using podman, `/proc/1/environ` contained `container=podman` instead. So I used `grep -qa '^container='` instead. – fstamour Oct 28 '22 at 18:14
A concise way to check for docker/lxc in a bash script is:
#!/bin/bash
if grep -sq 'docker\|lxc' /proc/1/cgroup; then
echo "I am running on Docker."
fi
-
-
-
FYI the echo command should use double quotes due to the single quote in "I'm" – TommyD Feb 14 '22 at 14:56
Handy Python function to check if running in Docker:
def in_docker():
""" Returns: True if running in a Docker container, else False """
with open('/proc/1/cgroup', 'rt') as ifh:
return 'docker' in ifh.read()
-
5Important Note! This does not appear to work when the container is running in kubernetes. Instead, replace the last line with 'kubepod' in place of 'docker'. (Or, put in an "or" statement that checks for both ;)) – JJC Jan 13 '19 at 03:20
-
2
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.

- 541
- 5
- 6
-
Depending on the OS, "init" might need to be replaced by "systemd". More information on systemd [here](https://www.tecmint.com/systemd-replaces-init-in-linux/). – BrianV Jun 23 '17 at 01:50
-
Yes, but the point wasn't the name of the init process, the point was the process number. – MillerGeek May 02 '18 at 14:31
-
1This seems to only work on Docker. In an LXC container It's returning Systemd PID 1 – MillerGeek May 02 '18 at 14:32
-
2It's now returning 1 in docker as well. It is usually `sh` and not `init` there, but it may be almost anything in either. – Jan Hudec May 06 '20 at 14:58
-
3Under docker, this is no longer the case - ```bash-5.0# cat /proc/1/sched bash (1, #threads: 1)``` – shalomb Jun 04 '20 at 10:57
As of 2022, with lxd v4.0+, none of the answers so far work for both docker and lxc.
- A
.dockerenv
file doesn't work for non-docker containers. - Checking that all hierarchies in
/proc/1/cgroup
are/
kinda maybe works. However, some hierarchies on non-containers are/init.scope
(Ubuntu 20.04 cgroup 0 and 1). So also not entirely reliable. - Checking for
container=lxc
in/proc/1/environ
works for lxc but not docker. Also, it requires root rights.
The only way I've found so far that works reliably on both CentOS and Ubuntu with lxc (4.0) containers and Docker, and also doesn't require root rights, is to check PID 2.
On all host systems, PID 2 is kthreadd
:
$ ps -p 2
PID TTY TIME CMD
2 ? 00:00:00 kthreadd
In containers, this PID either doesn't exist, or isn't kthreadd. Both docker and lxc show:
root@85396f8bce58:/# ps -p 2
PID TTY TIME CMD
root@85396f8bce58:/#
The best way seems to be to check /proc/2/status
:
$ head -n1 /proc/2/status
Name: kthreadd
So something like this seems to work:
if [ -n "$(grep 'kthreadd' /proc/2/status 2>/dev/null)" ]; then
echo "Not in container"
else
echo "In container";
fi

- 668
- 1
- 7
- 14
-
3
-
-
With Windows 10, WSL 2 distribution Ubuntu 22.04.1, it does not have process of pid 2. But it certainly is not docker environment. – zerox May 08 '23 at 04:43
The easiest way would be to check the environment. If you have the container=lxc
variable, you are within a container.
Otherwise, if you are root, you can try to perform mknod
or mount
operation, if it fails, you are most likely in a container with dropped capabilities.

- 116,210
- 12
- 97
- 73
-
This one works not only for docker (I didn't check that), but more importantly for lxd/lxc containers (checked), where `/proc/1/cgroup` does not allow you to detect that. – Draco Ater Jun 08 '16 at 06:37
-
5can you edit the answer with code instead of pseudocode? "container=lxc" ?is not proper anything. do you mean something like if [[ "lxc" = "$container" ]] ? – Alexander Mills Dec 20 '16 at 10:20
-
4I mean...it is weird, usually env variables are in all caps, so looking for some precision here – Alexander Mills Dec 20 '16 at 10:22
-
13`docker run alpine env` does not give anything that looks like that variable – Archimedes Trajano Mar 10 '19 at 16:01
This is an old question, but a REALLY good one. :)
I've written some automation scripts that we run on baremetal, VM and in a docker container, with logic branching based on which platform the script is executing on. In my case I have the privilege of creating both the container and the docker image, so this solution will only work if you are in control of the entire stack:
Snippet of Dockerfile:
FROM ubuntu:18.04
ENV PLATFORM="docker"
RUN apt update; \
...
The script can then just check the value of $PLATFORM
for desired outcomes on each platform:
#!/bin/bash
# Check for executor specification in environment
case $PLATFORM in
docker)
# If running in Docker, do this stuff
echo "Running containerized, proceeding..."
;;
virtual)
# If running in a VM, do different stuff
echo "Running on a VM, loading VM stuff..."
modprobe some-kernel-module
;;
*)
echo "Unknown executor specified! Exiting..."
exit 1
;;
esac
I've omitted baremetal in the above code to keep it concise.

- 150
- 2
- 7
This SO Q&A: "Find out if the OS is running in a virtual environment"; though not the same as the OP's question, it does indeed answer common cases of finding which container you're in (if at all).
In particular, install and read the code of this bash script which seems to work pretty well:
virt-what :
sudo apt install virt-what
-
Doesn't work with `virt-what` version 1.14-1 on Ubuntu 16.04. Needs patch. – Lucas Jan 04 '18 at 22:23
-
Interestingly, inside docker on windows, `virt-what` reports `hyperv`, just as my WSL2 bash shell does. – Peter V. Mørch Mar 03 '21 at 06:44
-
This does work in Ubuntu 20.04, it greps for "lxc" in /proc/1/environ – teknopaul Jun 22 '21 at 21:05
Check for all the solutions above in Python:
import os
def in_container():
proc_1 = r'/proc/1/sched'
if os.path.exists(proc_1):
with open(proc_1, 'r') as fp:
out = fp.read()
else:
out = ''
checks = [
'docker' in out,
'/lxc/' in out,
out.split(' ')[0] not in ('systemd', 'init',),
os.path.exists('./dockerenv'),
os.path.exists('/.dockerenv'),
os.path.exists('/.dockerinit'),
os.getenv('container') is not None
]
return any(checks)
if __name__ == '__main__':
print(in_container())
Proof of concept:
$ docker run --rm -it --mount type=bind,source=${PWD}/incontainer.py,target=/tmp/script.py python:3 python /tmp/script.py
True

- 4,154
- 2
- 32
- 52
-
This didn't work for me on Mac based docker container. Returns empty. Docker version 2.1.0.1 (37199). – splintercell Nov 26 '19 at 18:01
-
This one did: ```def is_non_docker(): return os.path.exists('/proc/1/cgroup')``` as per the accepted answer here https://stackoverflow.com/questions/20010199/how-to-determine-if-a-process-runs-inside-lxc-docker – splintercell Nov 26 '19 at 18:08
-
7You get a Useless Use Of Cat Award. And Useless Use Of Subprocess one. – Jan Hudec May 06 '20 at 15:00
-
-
You're right, I'll update it the answer even though it's still not all-encompassing. @JanHudec – blakev May 07 '20 at 17:32
-
-
In a docker container, entries /proc/self/cgroup
are mounted to cgroups on the host.
e.g. in a container
# awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/docker/22bd0c154fb4e0d1b6c748faf1f1a12116acc21ce287618a115ad2bea41256b3
whereas, the same on the host
$ awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/
Using something in the shell for a low profile test
is_running_in_container() {
awk -F: '/cpuset/ && $3 ~ /^\/$/ { c=1 } END{ exit c }' /proc/self/cgroup
}
if is_running_in_container; then
echo "Aye!! I'm in a container"
else
echo "Nay!! I'm not in a container"
fi

- 3,456
- 2
- 23
- 19
-
-
Works! Thanks! @sorin, it actually returns 1 only on host-level, but inside container returns zero. – Dmitry Shevkoplyas Oct 05 '22 at 23:53
My answer only applies for Node.js processes but may be relevant for some visitors who stumble to this question looking for a Node.js specific answer.
I had the same problem and relying on /proc/self/cgroup
I created an npm package for solely this purpose — to detect whether a Node.js process runs inside a Docker container or not.
The containerized npm module will help you out in Node.js. It is not currently tested in Io.js but may just as well work there too.

- 5,242
- 1
- 20
- 15
-
Thanks for this module, seems to be a couple of open fixes pending - are you still maintaining this? – stevokk Aug 02 '18 at 08:51
-
This module is no longer maintained. Additionally, a Node.js module that detects non-Docker container environments is needed. – Jeff Apr 29 '22 at 14:12
I have translated JJC's answer into ruby
def in_docker
File.open('/proc/1/cgroup', 'rt') do |f|
contents = f.read
return contents =~ /docker/i || contents =~ /kubepod/i
end
rescue StandardError => e
p 'Local development'
p e
false
end

- 3,116
- 2
- 30
- 44
A little bit of off topic, you can check if you're in a container or not in two ways:
cat /proc/1/environ|tr "\0" "\n"|grep container
: you will seecontainer
variable if you're in a container.ps -ef | grep '\['
: you will see nothing but only the grep process when you're in a container, which means there's no kernel process that you can see (e.g.[kthreadd]
). Caution: normal macOS also don't show kernel processes.
reference: this linux quiz page

- 386
- 5
- 16
Here's a solution in Ruby,
# Usage: DockerHelper.running_in_docker?
module DockerHelper
extend self
def running_in_docker?
!!(File.read("/proc/1/cgroup") =~ %r[^\d+:\w+:/docker/]) # !! => true/false
rescue Errno::ENOENT
false
end
end
If you like tests with your code, here's a spec in the gist.

- 1,248
- 12
- 14
The golang code get pid container_id and you can get map container_id get docker image
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
}

- 3,915
- 2
- 31
- 29
Docker is evolving day by day, so we can't say for sure if they are going to keep .dockerenv .dockerinit
in the future.
In most of the Linux flavours init
is the first process to start. But in case of containers this is not true.
#!/bin/bash
if ps -p1|grep -q init;then
echo "non-docker"
else
echo "docker"
fi

- 2,645
- 5
- 22
- 24
-
6
-
1It does not work in centos 7 as well. When I run in my host machine it says docker. Looks like systemd is running as process id 1 – Venkateswara Rao Jan 26 '18 at 05:02
-
@VenkateswaraRao - This must be run inside the container. The intent is to find out if you are inside a docker container or not. – Govind Kailas Jan 30 '18 at 04:43
-
1@GovindKailas: The problem is that this assumes that the normal PID one is `init`, which is not true on `systemd` or `launchd` based systems... – Gert van den Berg Feb 16 '18 at 14:24
-
3@SamThomas: launchd, upstart, Solaris SMF, systemd, Sys V style init, BSD style init (these two and some others might call their PID 1 `init` though), OpenRC, initng, runit. [See here](https://en.wikipedia.org/wiki/Init#Replacements_for_init). Most modern Linux-based systems would use `systemd`, some older ones, upstart.... All modern OS X systems would use `launchd` – Gert van den Berg May 23 '18 at 08:16
-
even systemd os (Ubuntu) call /lib/systemd/systemd /sbin/init when its pid 1 – teknopaul Jun 22 '21 at 21:09
Maybe this do the trick:
if [ -z $(docker ps -q) ]; then
echo "There is not process currently running"
else
echo "There are processes running"
fi
Is that what you want? Hope it helps =)

- 75
- 1
- 8
-
2No `docker` binary is available from inside of container, obviously. – toriningen Jul 05 '18 at 17:02
-
3Umm, this would fail in situations (e.g. gitlab docker-in-docker) where the controlling container has `docker` and access to the hosts' docker socket. – shalomb Jul 15 '18 at 21:02
-
2yeah, you're right, of course there isn't ^^. I got the wrong interpretation about the question back at the time when I read it. Thank you, Shalomb. – Leonardo Da Vinci Apr 16 '20 at 18:51