Wie kann festgestellt werden, ob ein Prozess in lxc / Docker ausgeführt wird?

172

Gibt es eine Möglichkeit festzustellen, ob ein Prozess (Skript) in einem lxc-Container ausgeführt wird (~ Docker-Laufzeit)? Ich weiß, dass einige Programme erkennen können, ob sie in einer virtuellen Maschine ausgeführt werden. Ist etwas Ähnliches für lxc / docker verfügbar?

Kumpel Varga
quelle
Es mag pedantisch erscheinen, aber es ist am besten, Ihre Frage neu zu formulieren, um ein Problem zu beschreiben, das Sie haben, und zu fragen, wie Sie es lösen können - ohne das besteht für die Frage eine höhere Wahrscheinlichkeit, geschlossen zu werden. In vielen Fällen ist es schwierig, diese Änderung vorzunehmen, aber in Ihren Fällen ist es nicht schwierig, sie einfach neu zu formulieren, wenn Sie dies wünschen.
Mah
Es gibt eine interessante Antwort, wenn dieser Befehl in einem Container ausgegeben wird: Betriebszeit
Scott Stensland

Antworten:

169

Der zuverlässigste Weg ist zu überprüfen /proc/1/cgroup. Hier erfahren Sie, welche Kontrollgruppen der Init-Prozess enthält. Wenn Sie sich nicht in einem Container befinden, gilt dies /für alle Hierarchien. Wenn Sie sich in einem Container befinden, wird der Name des Ankerpunkts angezeigt. Mit LXC / Docker - Container, wird es so etwas wie /lxc/<containerid>oder /docker/<containerid>sind.

jpetazzo
quelle
13
Docker verwendet jetzt dockerstatt lxcin diesen Pfaden
Andy
4
Funktioniert nicht für lxd / lxc-Container, aber stackoverflow.com/a/20010626/170230 .
Draco Ater
In späteren Versionen von systemd können Sie sich anscheinend nicht auf Prozess 1 verlassen, der /für alle cgroups verwendet wird. Auf meinem Debian 9-System (systemd 232) befinden sich nur drei der zehn cgroups ( 3:cpuset, 4:perf_eventund 7:freezer) an der Wurzel. der Rest ist unter /init.scope. Trotzdem denke ich, dass das Durchsuchen dieser Datei :/docker/im Moment wahrscheinlich die zuverlässigste Heuristik ist.
cjs
2
grep 'docker\|lxc' /proc/1/cgroupfunktioniert für mich auf Docker 18.09.
Rypel
1
Ich arbeite nicht für mich. Host Ubuntu 19.04, Gast Ubuntu 18.04 mit LXC-privilegiertem Container. / proc / 1 / cgroup enthält NICHT die lxc-Zeichenfolge.
Gab
157

Docker erstellt eine .dockerenvDatei im Stammverzeichnis des Verzeichnisbaums im Container. Sie können dieses Skript zur Überprüfung ausführen

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


MEHR: Ubuntu hat tatsächlich ein Bash-Skript: /bin/running-in-containerund es kann tatsächlich den Containertyp zurückgeben, in dem es aufgerufen wurde. Könnte hilfreich sein. Ich weiß aber nichts über andere große Distributionen.

at0S
quelle
13
Wichtiger Hinweis: Die .dockerinitDatei wurde in neueren Versionen von Docker entfernt , sodass diese Methode nicht mehr funktioniert. Zum jetzigen Zeitpunkt wird die .dockerenvDatei immer noch aufbewahrt, sodass sie möglicherweise stattdessen verwendet werden könnte.
Jason R
On Debian /bin/running-in-containerwird bereitgestellt von upstart. Mit dem Übergang zu systemd könnte es verschwinden. Ich hoffe nicht - es klingt nützlich!
Max Murphy
"oben auf dem Verzeichnisbaum", was bedeutet das? wo ist das?
Alexander Mills
3
Andere haben darauf hin , dass Prüfung hingewiesen .dockerenvwird nicht empfohlen
Dave
1
Hinweis: Das Testen auf .dockerenv funktioniert nur, wenn die Laufzeit ein Docker-Daemon ist. Wenn Sie Podman oder etwas anderes verwenden, schlägt dies fehl.
Benjamin Kircher
22

Auf einem neuen Ubuntu 16.04-System, neues Systemd & lxc 2.0

sudo grep -qa container=lxc /proc/1/environ
larss
quelle
Dies funktioniert bei mir unter Ubuntu Focal 20.04. Keine der Antworten über diesem Punkt traf zu.
Jonathan Hartley
16

Eine kurze Möglichkeit, in einem Bash-Skript nach Docker zu suchen, ist:

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

Praktische Python-Funktion, um zu überprüfen, ob sie in Docker ausgeführt wird:

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()
JJC
quelle
2
Wichtige Notiz! Dies scheint nicht zu funktionieren, wenn der Container in Kubernetes ausgeführt wird. Ersetzen Sie stattdessen die letzte Zeile durch "Kubepod" anstelle von "Docker". (Oder geben Sie eine "oder" -Anweisung ein, die beide überprüft;))
JJC
1
Es ist, kubepodsdenke ich.
Rookie099
9

Wir verwenden den Zeitplan des Prozesses (/ proc / $ PID / sched), um die PID des Prozesses zu extrahieren. Die PID des Prozesses im Container unterscheidet sich von der PID auf dem Host (einem Nicht-Container-System).

Beispielsweise gibt die Ausgabe von / proc / 1 / sched für einen Container Folgendes zurück:

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

Auf einem Nicht-Container-Host:

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

Dies hilft zu unterscheiden, ob Sie sich in einem Container befinden oder nicht.

Gründer
quelle
Je nach Betriebssystem muss "init" möglicherweise durch "systemd" ersetzt werden. Weitere Informationen zu systemd finden Sie hier .
BrianV
Ja, aber der Punkt war nicht der Name des Init-Prozesses, der Punkt war die Prozessnummer.
MillerGeek
Dies scheint nur unter Docker zu funktionieren. In einem LXC-Container gibt es Systemd PID 1
MillerGeek
Es gibt jetzt auch 1 im Docker zurück. Es ist normalerweise shund nicht initda, aber es kann fast alles in beiden sein.
Jan Hudec
Unter Docker ist dies nicht mehr der Fall -bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
Shalomb
5

Am einfachsten wäre es, die Umgebung zu überprüfen. Wenn Sie die habencontainer=lxc Variable haben, befinden Sie sich in einem Container.

Andernfalls, wenn Sie als root angemeldet sind, können Sie versuchen , auszuführen mknododer mountBetrieb, wenn es ausfällt, Sie sind am ehesten in einem Behälter mit sank Fähigkeiten.

knarren
quelle
Dieser funktioniert nicht nur für Docker (das habe ich nicht überprüft), sondern vor allem für lxd / lxc-Container (aktiviert), bei denen Sie /proc/1/cgroupdies nicht erkennen können.
Draco Ater
2
Können Sie die Antwort mit Code anstelle von Pseudocode bearbeiten? "container = lxc"? ist nichts richtig. meinst du so etwas wie wenn [["lxc" = "$ container"]]?
Alexander Mills
3
Ich meine ... es ist seltsam, normalerweise sind env-Variablen in Großbuchstaben, also suchen Sie hier nach Präzision
Alexander Mills
7
docker run alpine envgibt nichts, was wie diese Variable aussieht
Archimedes Trajano
3

Meine Antwort gilt nur für Node.js-Prozesse , kann jedoch für einige Besucher relevant sein, die auf diese Frage stoßen und nach einer Node.js-spezifischen Antwort suchen.

Ich hatte das gleiche Problem und habe /proc/self/cgroupmich darauf verlassen, dass ich ein npm-Paket erstellt habe nur zu diesem Zweck - um festzustellen, ob ein Node.js-Prozess in einem Docker-Container ausgeführt wird oder nicht.

Das containerisierte npm-Modul hilft Ihnen in Node.js. Es wird derzeit nicht in Io.js getestet, kann aber auch dort funktionieren.

Martin Tajur
quelle
Vielen Dank für dieses Modul, anscheinend stehen noch einige offene Korrekturen an - behalten Sie dies noch bei?
Stevokk
2

Suchen Sie in Python nach allen oben genannten Lösungen:

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

Konzeptioneller Beweiß:

$ docker run --rm -it --mount type=bind,source=${PWD}/incontainer.py,target=/tmp/script.py python:3 python /tmp/script.py
True
Blakev
quelle
Dies funktionierte bei mir auf einem Mac-basierten Docker-Container nicht. Gibt leer zurück. Docker Version 2.1.0.1 (37199).
Splittercell
Dieser tat def is_non_docker(): return os.path.exists('/proc/1/cgroup')wie pro die akzeptierte Antwort hier stackoverflow.com/questions/20010199/...
Splintercell
2
Sie erhalten einen Useless Use Of Cat Award. Und nutzlose Verwendung von Teilprozess eins.
Jan Hudec
Ja, das ist eine ganz neue Ebene von unnötig cat ! Schön :-D
Timmmm
Sie haben Recht, ich werde die Antwort aktualisieren, obwohl sie immer noch nicht allumfassend ist. @ JanHudec
Blakev
1

Docker entwickelt sich von Tag zu Tag weiter, daher können wir nicht sicher sagen, ob sie .dockerenv .dockerinitin Zukunft beibehalten werden.

In den meisten Linux-Varianten initist der erste Prozess zu starten. Bei Containern ist dies jedoch nicht der Fall.

#!/bin/bash
if ps -p1|grep -q init;then  
  echo "non-docker" 
else 
  echo "docker" 
fi
Govind Kailas
quelle
6
@RomanTrofimov LXC / Docker auch nicht. Was für ein lustiger Kommentar.
Abourget
1
Es funktioniert auch nicht in Centos 7. Wenn ich auf meinem Host-Computer ausgeführt werde, wird Docker angezeigt. Es sieht so aus, als würde systemd als Prozess-ID 1 ausgeführt
Venkateswara Rao
@VenkateswaraRao - Dies muss im Container ausgeführt werden. Sie möchten herausfinden, ob Sie sich in einem Docker-Container befinden oder nicht.
Govind Kailas
1
@ GovindKailas: Das Problem ist, dass dies voraussetzt, dass die normale PID ist init, was auf systemdoder launchdbasierend auf Systemen nicht wahr ist ...
Gert van den Berg
3
@SamThomas: launchd, upstart, Solaris SMF, systemd, Init im Sys V-Stil, init im BSD-Stil (diese beiden und einige andere nennen jedoch möglicherweise ihre PID 1 init), OpenRC, initng, runit. Siehe hier . Die meisten modernen Linux-basierten Systeme würden verwenden systemd, einige ältere, Emporkömmling ... Alle modernen OS X-Systeme würden verwendenlaunchd
Gert van den Berg
0

Diese SO-Fragen und Antworten: "Finden Sie heraus, ob das Betriebssystem in einer virtuellen Umgebung ausgeführt wird" ; Obwohl dies nicht mit der Frage des OP identisch ist, beantwortet es tatsächlich häufige Fälle, in denen festgestellt wird, in welchem ​​Container Sie sich befinden (wenn überhaupt).

Installieren und lesen Sie insbesondere den Code dieses Bash-Skripts, der anscheinend recht gut funktioniert:

virt-what :

sudo apt install virt-what
Kaiwan
quelle
Funktioniert nicht mit virt-whatVersion 1.14-1 unter Ubuntu 16.04. Benötigt Patch.
Lucas
0

Ich habe JJCs Antwort in Rubin übersetzt

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
Souradeep Nanda
quelle
-1

In einem Docker-Container werden Einträge /proc/self/cgroupin cgroups auf dem Host bereitgestellt.

zB in einem Behälter

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

während das gleiche auf dem Host

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

Verwenden Sie etwas in der Shell für einen 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
Shalomb
quelle
Gibt bei beiden 1 zurück.
Sorin
-4

Vielleicht macht das den Trick:

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

Ist es das was du willst? Hoffe es hilft =)

Leonardo Da Vinci
quelle
1
dockerOffensichtlich ist im Inneren des Containers keine Binärdatei verfügbar.
Toriningen
3
Umm, dies würde in Situationen (z. B. Gitlab Docker-in-Docker) fehlschlagen, in denen der steuernde Container über dockerZugriff auf den Docker-Socket des Hosts verfügt.
Shalomb
1
Ja, du hast recht, natürlich gibt es keine ^^. Ich habe die Frage zu dem Zeitpunkt, als ich sie las, falsch interpretiert. Danke, Shalomb.
Leonardo Da Vinci