プロセスがlxc / Docker内で実行されているかどうかを判断する方法は?


172

プロセス(スクリプト)がlxcコンテナー(〜Dockerランタイム)内で実行されているかどうかを確認する方法はありますか?一部のプログラムは、仮想マシン内で実行されているかどうかを検出できることを知っています。lxc/ dockerでも同様のものが利用できますか?


見た目は奇妙に思えるかもしれませんが、発生している問題を説明するために質問を書き直し、それを解決する方法を尋ねるのが最善です。それがなければ、質問が閉じられる可能性が高くなります。多くの場合、その変更を行うのは困難ですが、あなたの場合は、必要に応じて単純に言い換えることは難しくありません。
mah

コンテナ内でこのコマンドを発行すると、興味深い応答があります。稼働時間
Scott Stensland 2017

回答:


169

最も信頼できる方法はチェックすること/proc/1/cgroupです。これにより、initプロセスの制御グループがわかります。コンテナー内にいない場合は/、すべての階層が対象になります。コンテナー内にいるときは、アンカーポイントの名前が表示されます。LXC / Dockerコンテナを使用すると/lxc/<containerid>/docker/<containerid>それぞれのようなものになります。


13
docker はこれらのパスではdockerなくを使用するようになりlxcました
Andy

4
lxd / lxcコンテナでは機能しませんが、stackoverflow.com / a / 20010626/170230 では機能します。
Draco Ater 2016年

systemdの以降のバージョンでは/、すべてのcgroup にプロセス1を使用することはできないようです。私のDebian 9システム(systemd 232)では、10個のcgroup(3:cpuset4:perf_eventおよび7:freezer)の3つだけがルートにあります。残りは下/init.scopeです。そうは言っても、そのファイルを検索すること:/docker/は、おそらく現時点で最も信頼できるヒューリスティックだと思います。
cjs 2018

2
grep 'docker\|lxc' /proc/1/cgroupDocker 18.09で動作します。
rypel

1
私のために働いていません。LXC特権コンテナを使用して、Ubuntu 19.04、ゲストUbuntu 18.04をホ​​ストします。/ proc / 1 / cgroupにはlxc文字列が含まれていません。
Gab

157

Dockerは、.dockerenvコンテナー内のディレクトリツリーのルートにファイルを作成します。このスクリプトを実行して確認できます

#!/bin/bash
if [ -f /.dockerenv ]; then
    echo "I'm inside matrix ;(";
else
    echo "I'm living in real world!";
fi


詳細: Ubuntuには実際にbashスクリプト/bin/running-in-containerがあります。実際には、起動されたコンテナーのタイプを返すことができます。役立つ場合があります。ただし、他の主要なディストリビューションについては知らない。


13
重要な注意:最近のバージョンのDockerでは.dockerinitファイルが削除されいるため、この方法は機能しなくなります。これを書いている時点では、.dockerenvファイルはまだ残っているので、おそらく代わりに使用できます。
Jason R

Debianでは/bin/running-in-containerが提供していupstartます。systemdへの移行により、それはなくなるかもしれません。私はそうではないと思います-それは便利に聞こえます!
Max Murphy

「ディレクトリツリーの上」、それはどういう意味ですか?それはどこですか?
Alexander Mills

3
他の人はチェック.dockerenv推奨
Dave

1
注:.dockerenvのテストは、ランタイムがdockerデーモンの場合にのみ機能します。podmanやその他のものを使用している場合、これは失敗します。
Benjamin Kircher

22

新しいUbuntu 16.04システム、新しいsystemdおよびlxc 2.0

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

これはUbuntuフォーカル20.04で動作します。この点を超える答えはありませんでした。
Jonathan Hartley

16

bashスクリプトでdockerを確認する簡潔な方法は次のとおりです。

#!/bin/bash
if grep docker /proc/1/cgroup -qa; then
   echo I'm running on docker.
fi

14

Dockerで実行されているかどうかを確認する便利なPython関数:

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()

2
重要な注意点!コンテナーがkubernetesで実行されている場合、これは機能していないようです。代わりに、最後の行を「docker」の代わりに「kubepod」に置き換えます。(または、両方をチェックする「or」ステートメントを挿入します;))
JJC '13

1
それはkubepods私が推測することです。
rookie099

9

プロセスのPIDを抽出するには、プロシージャのスケジュール(/ proc / $ PID / sched)を使用します。コンテナー内のプロセスのPIDは、ホスト(コンテナー以外のシステム)のPIDとは異なります。

たとえば、コンテナでの/ proc / 1 / schedの出力は次のようになります。

root@33044d65037c:~# cat /proc/1/sched | head -n 1
bash (5276, #threads: 1)

非コンテナホスト上:

$ cat /proc/1/sched  | head -n 1
init (1, #threads: 1)

これは、コンテナー内にいるかどうかを区別するのに役立ちます。


OSによっては、「init」を「systemd」に置き換える必要がある場合があります。systemdの詳細については、こちらをご覧ください
BrianV 2017年

はい。ただし、ポイントは初期化プロセスの名前ではなく、プロセス番号でした。
MillerGeek

これはDockerでのみ機能するようです。LXCコンテナではそれはsystemdにPID 1を返します
MillerGeek

Dockerでも1を返します。通常shinitあり、ありませんが、どちらでもほぼ何でもかまいません。
Jan Hudec

ドッカーの下では、これはもうbash-5.0# cat /proc/1/sched bash (1, #threads: 1)
当てはまり

5

最も簡単な方法は、環境をチェックすることです。あなたが持っている場合container=lxc、変数を、あなたは、コンテナ内にあります。

それ以外の場合、rootである場合は実行mknodまたはmount操作を試行できますが、失敗した場合は、機能がドロップされたコンテナー内にいる可能性があります。


これは、Docker(チェック/proc/1/cgroupしていません)だけでなく、lxd / lxcコンテナー(チェック済み)でも機能します。
Draco Ater 2016年

2
疑似コードの代わりにコードで答えを編集できますか?"container = lxc"?何も適切ではありません。if [["lxc" = "$ container"]]のような意味ですか?
Alexander Mills

3
つまり、奇妙なことです。通常、env変数はすべて大文字なので、ここで精度を探します
Alexander Mills

7
docker run alpine envその変数のように見えるものは何も与えません
Archimedes Trajano

3

私の回答はNode.jsプロセスにのみ適用されますが、Node.js固有の回答を探してこの質問につまずく一部の訪問者に関連する可能性があります。

私は同じ問題を抱えており、Node.jsプロセスがDockerコンテナー内で実行されているかどうかを検出するためだけに、この目的のためだけにnpmパッケージ/proc/self/cgroupを作成しました。

コンテナNPMモジュールは Node.js.であなたを助けます 現在Io.jsでテストされていませんが、そこでも動作する可能性があります。


このモジュールをありがとう、いくつかの未解決の修正が保留中のようです-これをまだ維持していますか?
stevokk 2018

2

上記のすべての解決策を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('/.dockerinit'),
        os.getenv('container') is not None
    ]
    return any(checks)


if __name__ == '__main__':
    print(in_container())

コンセプトの証明:

$ docker run --rm -it --mount type=bind,source=${PWD}/incontainer.py,target=/tmp/script.py python:3 python /tmp/script.py
True

これは、MacベースのDockerコンテナでは機能しませんでした。空を返します。Dockerバージョン2.1.0.1(37199)。
splintercell

これは、次のdef is_non_docker(): return os.path.exists('/proc/1/cgroup')とおりです。ここで受け入れられた回答に従って、stackoverflow.com
questions

2
あなたは猫の役に立たない賞を受賞しました。そして、サブプロセス1の無用な使用。
Jan Hudec

ええ、これはまったく新しいレベルの不必要なものcatです。いいです

正解です。すべてを網羅しているわけではありませんが、答えを更新します。@JanHudec
blakev

1

Dockerは日々進化.dockerenv .dockerinitしているため、今後も継続するかどうかはわかりません 。

ほとんどのLinuxフレーバーinitは、最初に開始するプロセスです。しかし、コンテナの場合、これは真実ではありません。

#!/bin/bash
if ps -p1|grep -q init;then  
  echo "non-docker" 
else 
  echo "docker" 
fi

6
@RomanTrofimov LXC / Dockerも同様です。なんて面白いコメントだ。
2017

1
CentOS 7でも機能しません。ホストマシンで実行すると、Dockerと表示されます。systemdがプロセスID 1として実行されているようです
Venkateswara Rao

@VenkateswaraRao-これはコンテナ内で実行する必要があります。その目的は、Dockerコンテナー内にいるかどうかを確認することです。
Govind Kailas

1
@GovindKailas:問題は、これは通常のPIDがinitであると想定していることです。これは、システムsystemdまたはlaunchdベースのシステムには当てはまりません...
Gert van den Berg

3
@SamThomas:launchd、upstart、Solaris SMF、systemd、Sys Vスタイルのinit、BSDスタイルのinit(これら2つと他のいくつかはPID 1と呼ぶことinitもあります)、OpenRC、initng、runit。こちらをご覧ください。最近のほとんどのLinuxベースのシステムはを使用しsystemd、一部の古いシステムは新興します。最新のOS Xシステムはすべて使用しますlaunchd
Gert van den Berg

0

このSOに関するQ&A:「OSが仮想環境で実行されているかどうかを確認してください」 ; OPの質問と同じではありませんが、実際にどのコンテナーにいるかを(あるとしても)見つける一般的なケースに答えます。

特に、このbashスクリプトのコードをインストールして読んでください。

virt-what

sudo apt install virt-what

virt-whatUbuntu 16.04のバージョン1.14-1では動作しません。パッチが必要です。
Lucas

0

JJCの答えをルビーに翻訳しました

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

-1

Dockerコンテナーでは、エントリー/proc/self/cgroupはホストのcgroupにマウントされます。

例:コンテナ内

# awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/docker/22bd0c154fb4e0d1b6c748faf1f1a12116acc21ce287618a115ad2bea41256b3

一方、ホスト上では同じ

$ awk -F: '/cpuset/' /proc/self/cgroup
3:cpuset:/

シェルで何かを使用して目立たないテスト

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

両方で1を返します。
ソリン

-4

多分これはトリックをします:

if [ -z $(docker ps -q) ]; then
    echo "There is not process currently running"
else
    echo "There are processes running"
fi

それでいいの?それが役に立てば幸い=)


1
docker明らかに、コンテナの内部から利用できるバイナリはありません。
toriningen

3
ええと、これは、制御コンテナがdockerホストのDockerソケットにアクセスしてアクセスできる状況(gitlab docker-in-dockerなど)では失敗します。
shalomb 2018

1
ええ、あなたは正しい、もちろんありません^^。質問を読んだときに、その質問について間違った解釈をしました。ありがとう、シャローム。
レオナルドダヴィンチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.