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

90,862

Solution 1

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.

Solution 2

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.

Solution 3

On a new ubuntu 16.04 system, new systemd & lxc 2.0

sudo grep -qa container=lxc /proc/1/environ

Solution 4

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

Solution 5

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()
Share:
90,862

Related videos on Youtube

Mate Varga
Author by

Mate Varga

Updated on August 03, 2022

Comments

  • Mate Varga
    Mate Varga almost 2 years

    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?

    • mah
      mah over 10 years
      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.
    • Scott Stensland
      Scott Stensland over 7 years
      there is an interesting response when issuing this command while inside a container : uptime
  • Andy
    Andy over 8 years
    docker now uses docker instead of lxc in those paths
  • Draco Ater
    Draco Ater about 8 years
    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
    Draco Ater about 8 years
    Does not work for lxd/lxc containers, but stackoverflow.com/a/20010626/170230 does.
  • Max Murphy
    Max Murphy almost 8 years
    On Debian /bin/running-in-container is provided by upstart. With the transition to systemd it might go away. I hope not - it sounds useful!
  • Alexander Mills
    Alexander Mills over 7 years
    "on top of directory tree", what does that mean? where is that?
  • Alexander Mills
    Alexander Mills over 7 years
    can 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
    Alexander Mills over 7 years
    I mean...it is weird, usually env variables are in all caps, so looking for some precision here
  • abourget
    abourget over 7 years
    @RomanTrofimov LXC/Docker doesn't either. What a funny comment.
  • BrianV
    BrianV about 7 years
    Depending on the OS, "init" might need to be replaced by "systemd". More information on systemd here.
  • Lucas
    Lucas over 6 years
    Doesn't work with virt-what version 1.14-1 on Ubuntu 16.04. Needs patch.
  • Venkateswara Rao
    Venkateswara Rao over 6 years
    It 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
  • Govind Kailas
    Govind Kailas over 6 years
    @VenkateswaraRao - This must be run inside the container. The intent is to find out if you are inside a docker container or not.
  • Gert van den Berg
    Gert van den Berg over 6 years
    @GovindKailas: The problem is that this assumes that the normal PID one is init, which is not true on systemd or launchd based systems...
  • cjs
    cjs over 6 years
    With 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.
  • MillerGeek
    MillerGeek about 6 years
    Yes, but the point wasn't the name of the init process, the point was the process number.
  • MillerGeek
    MillerGeek about 6 years
    This seems to only work on Docker. In an LXC container It's returning Systemd PID 1
  • Gert van den Berg
    Gert van den Berg about 6 years
    @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. Most modern Linux-based systems would use systemd, some older ones, upstart.... All modern OS X systems would use launchd
  • toriningen
    toriningen almost 6 years
    No docker binary is available from inside of container, obviously.
  • shalomb
    shalomb almost 6 years
    Umm, this would fail in situations (e.g. gitlab docker-in-docker) where the controlling container has docker and access to the hosts' docker socket.
  • stevokk
    stevokk almost 6 years
    Thanks for this module, seems to be a couple of open fixes pending - are you still maintaining this?
  • Dave
    Dave over 5 years
    Others have pointed out that checking .dockerenv is not recommended
  • okutane
    okutane over 5 years
    For me .dockerenv is more like edge of the world from "13th floor".
  • JJC
    JJC over 5 years
    Important 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 ;))
  • rypel
    rypel over 5 years
    grep 'docker\|lxc' /proc/1/cgroup works for me on Docker 18.09.
  • Archimedes Trajano
    Archimedes Trajano over 5 years
    docker run alpine env does not give anything that looks like that variable
  • rubicks
    rubicks about 5 years
    Here's a tighter (extended) regex that assumes a sha256 hash in the basename position: grep -Eq '/(lxc|docker)/[[:xdigit:]]{64}' /proc/1/cgroup
  • Boop
    Boop almost 5 years
    Combining 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)
  • rookie099
    rookie099 almost 5 years
    It's kubepods I guess.
  • Gab
    Gab almost 5 years
    Not working for me. Host Ubuntu 19.04, guest Ubuntu 18.04 using LXC privileged container. /proc/1/cgroup does NOT contain the lxc string.
  • Benjamin Kircher
    Benjamin Kircher almost 5 years
    Note: testing for .dockerenv works only if the runtime is docker daemon. If you are using podman or something else this fails.
  • splintercell
    splintercell over 4 years
    This didn't work for me on Mac based docker container. Returns empty. Docker version 2.1.0.1 (37199).
  • splintercell
    splintercell over 4 years
    This one did: def is_non_docker(): return os.path.exists('/proc/1/cgroup') as per the accepted answer here stackoverflow.com/questions/20010199/…
  • sorin
    sorin over 4 years
    Returns 1 on both.
  • Leonardo Da Vinci
    Leonardo Da Vinci about 4 years
    yeah, 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.
  • Jonathan Hartley
    Jonathan Hartley about 4 years
    This works for me on Ubuntu focal 20.04. None of the answers above this point did.
  • Jan Hudec
    Jan Hudec about 4 years
    It'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
    Jan Hudec about 4 years
    You get a Useless Use Of Cat Award. And Useless Use Of Subprocess one.
  • Timmmm
    Timmmm about 4 years
    Yeah this is a whole new level of unnecessary cat! Nice one :-D
  • blakev
    blakev about 4 years
    You're right, I'll update it the answer even though it's still not all-encompassing. @JanHudec
  • shalomb
    shalomb about 4 years
    Under docker, this is no longer the case - bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
  • Meir Gabay
    Meir Gabay almost 4 years
    It'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
  • Daniel Griscom
    Daniel Griscom over 3 years
    Ubuntu 18.0.4 doesn't have /bin/running-in-container.
  • Treviño
    Treviño over 3 years
    Not sure this is correct when using a schroot instead, in such case the cgroup is still the same
  • Peter V. Mørch
    Peter V. Mørch over 3 years
    Interestingly, inside docker on windows, virt-what reports hyperv, just as my WSL2 bash shell does.
  • oNaiPs
    oNaiPs about 3 years
    Thanks @DanielGriscom that looks way better.
  • Alek
    Alek about 3 years
    Thanks! it works for lxc! Can you please explain why '-a' is needed? Isn't grep -q container=lxc /proc/1/environ enough?
  • erik
    erik about 3 years
    This didn't work when my container was running within kubernetes.
  • teknopaul
    teknopaul about 3 years
    This does work in Ubuntu 20.04, it greps for "lxc" in /proc/1/environ
  • teknopaul
    teknopaul about 3 years
    even systemd os (Ubuntu) call /lib/systemd/systemd /sbin/init when its pid 1
  • Hi-Angel
    Hi-Angel almost 3 years
    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.
  • Adam Azarchs
    Adam Azarchs almost 3 years
    /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
  • Brett Sutton
    Brett Sutton over 2 years
    On my docker image: cat /proc/1/cgroup 0::/ so doesn't work.
  • Henrique Capozzi
    Henrique Capozzi over 2 years
    I'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'
  • TommyD
    TommyD over 2 years
    FYI the echo command should use double quotes due to the single quote in "I'm"
  • Jeff
    Jeff about 2 years
    This module is no longer maintained. Additionally, a Node.js module that detects non-Docker container environments is needed.