44

I was trying to find out if my script was running inside a docker container or not within the python script.

Something like:

if inside_docker():
    do_stuff()
else:
    do_some_other_stuff()

to do this the only hacky way I found out how to do it is that I can inspect the hostname (with platform.node()) and if the hostname is not the same as my computer then its not in docker (since hostnames docker are some weird hash or something).

Instead I was thinking something a bit more programatic as follows:

  1. first detect docker with cat /proc/1/cgroup
  2. then compare the name those hierarchies with the docker id/hash.

Something like:

from subprocess import call
import platform
hash = call('cat /proc/1/cgroup')
hostname = hostname = platform.node()
docker_boolean = does_hostname_contain_docker_hash(hash, hostname) # true or false

I thought something like that would work but I can't even get to call the cat /proc/1/cgroup without an error. If I am in docker I get the error:

>>> from subprocess import call
>>> call('from subprocess import call')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

any ideas how to fix that?


as a side node I was thinking of making my solution portable but docker is suppose to be portable already so if I am in docker this should always work...

Charlie Parker
  • 5,884
  • 57
  • 198
  • 323
  • 2
    What if you fed an environment variable to your container? That way your python app would only be able to retrieve it if it was running in the container. – Kyle Truong May 09 '17 at 20:15
  • or even better I could just have that environment be defined in the docker file, I don't want to have to pass something weird to every container I ever use XD – Charlie Parker May 09 '17 at 20:17
  • Can you tell us the use case? Will you always have control over the execution context? To be honest if you don't, there is absolutely no way (user could 'game / trick' any one of the methods / answers). – johnharris85 May 09 '17 at 23:25
  • @johnharris85 its just to be able to specify to the script where the data files are when I run it locally vs using docker in a cluster. – Charlie Parker May 11 '17 at 18:59

6 Answers6

64

I think the preferred way to do this is through environment variables. If you're creating your Python app from a Dockerfile, you could specify the 'ENV' directive:

https://docs.docker.com/engine/reference/builder/#env

Dockerfile:

...
ENV AM_I_IN_A_DOCKER_CONTAINER Yes

which could then be read from your app with something like:

python_app.py:

import os

SECRET_KEY = os.environ.get('AM_I_IN_A_DOCKER_CONTAINER', False)

if SECRET_KEY:
    print('I am running in a Docker container')
boatcoder
  • 17,525
  • 18
  • 114
  • 178
Kyle Truong
  • 2,545
  • 8
  • 34
  • 50
  • 5
    Small detail, but `SECRET_KEY` will always evaluate to `True` if the default is `'NOPE'`. – fenceop Oct 21 '17 at 12:27
  • To me more favor for a simpler approach right from python code is [here](https://stackoverflow.com/a/48710609/248616) – Nam G VU Aug 28 '22 at 04:18
38

The is-docker package for npm suggests a robust approach, ported here to Python 2.6+:

import os
def is_docker():
    path = '/proc/self/cgroup'
    return (
        os.path.exists('/.dockerenv') or
        os.path.isfile(path) and any('docker' in line for line in open(path))
    )
crizCraig
  • 8,487
  • 6
  • 54
  • 53
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
9
import os, re

path = "/proc/self/cgroup"

def is_docker():
  if not os.path.isfile(path): return False
  with open(path) as f:
    for line in f:
      if re.match("\d+:[\w=]+:/docker(-[ce]e)?/\w+", line):
        return True
    return False

print(is_docker())
Matt
  • 68,711
  • 7
  • 155
  • 158
  • 2
    This would fail if `--pid=host` is used (i.e, if the container shares the PID namespace with the host). To make it work your code needs a minimal change: `path = "/proc/" + os.getpid() + "/cgroup"` – Ricardo Branco May 09 '17 at 22:51
  • This technique isn't working for me. I'm using docker for mac. The lines in `/proc/12/cgroup` include things like : `13:name=systemd:/docker-ce/docker/3ee...\n`. The regex misses due to the `=` in second field and the `/docker-ce` in the third field. – Jason R. Coombs Feb 09 '18 at 16:43
  • 1
    @JasonR.Coombs that should cover the old and new layouts now – Matt Feb 21 '18 at 04:59
  • There is a magic `/proc/self` symlink pointing to the right PID, so you don't need to call `os.getpid()`, but can let kernel do the work inside path resolution directly. – Jan Hudec May 06 '20 at 15:30
7

In Python 3.4+ this should work nice

from pathlib import Path

def is_docker():
    cgroup = Path('/proc/self/cgroup')
    return Path('/.dockerenv').is_file() or cgroup.is_file() and 'docker' in cgroup.read_text()
simonzack
  • 19,729
  • 13
  • 73
  • 118
miigotu
  • 1,387
  • 15
  • 15
4

Similar to the is-docker package for npm, I've created jaraco.docker with an is_docker function. For Python 3.5+ with that package installed:

from jaraco.docker import is_docker
if is_docker():
    print("In docker")
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • Yeah, it's been 3 years. Not working in 2020 :) – swdev Feb 13 '21 at 22:54
  • Not sure what you mean it's not working. [Works great for me](https://gist.github.com/638896dfeff10074baa971e70cd2916f) and there are [no issues filed with the project](https://github.com/jaraco/jaraco.docker/issues). Also, it's 2021. – Jason R. Coombs Feb 15 '21 at 18:51
  • Haha, right. I always forgot about new year! Yeah, sorry, when I tried it, got error. But then I realize I can simply supply env variable saying, IN_DOCKER. So, I use that – swdev Feb 16 '21 at 10:51
  • To me more favor for a simpler approach right from python code is [here](https://stackoverflow.com/a/48710609/248616) – Nam G VU Aug 28 '22 at 04:19
  • I'm not sure it's simpler for each and every potential user to make a copy/paste of the code. Of course, any user is welcome to do so, but if there's a bug in the original source or if the technique needs to evolve for changes in Docker, then all of the copies will need to get updated. It seems simpler in the long run to provide an implementation with a single source of truth and mechanism for updating. – Jason R. Coombs Sep 22 '22 at 17:03
0

If you are using nodeJS

is-docker is a popular npm packages to accomplish this.

import isDocker from 'is-docker';

if (isDocker()) {
    console.log('Running inside a Docker container');
}

Michael Nelles
  • 5,426
  • 8
  • 41
  • 57
  • The OP is about python, so To me more favor for a simpler approach right from python code is [here](https://stackoverflow.com/a/48710609/248616) – Nam G VU Aug 28 '22 at 04:19