Bir işlemin lxc / Docker içinde çalışıp çalışmadığını nasıl belirleyebilirim?


172

Bir işlemin (komut dosyasının) bir lxc kapsayıcısında (~ Docker çalışma zamanı) çalışıp çalışmadığını belirlemenin herhangi bir yolu var mı? Bazı programların sanal bir makine içinde çalışıp çalışmadığını algılayabildiğini biliyorum, lxc / docker için benzer bir şey var mı?


Bilgiçlik gibi görünebilir, ancak yaşadığınız bir sorunu tanımlamak ve nasıl çözüleceğini sormak için sorunuzu yeniden ifade etmek en iyisi olacaktır - bu olmadan soru daha yüksek bir kapalı olma şansına sahiptir. Çoğu durumda bu değişikliği yapmak zordur, ancak sizinkinde dilerseniz sadece yeniden ifade etmek zor olmaz.
mah

bir konteynerin içindeyken bu komutu verirken ilginç bir yanıt var: uptime
Scott Stensland

Yanıtlar:


169

En güvenilir yol kontrol etmektir /proc/1/cgroup. Başlangıç ​​sürecinin kontrol gruplarını ve bir kapta olmadığınızda , bu /tüm hiyerarşiler için size söyleyecektir . Bir kabın içindeyken , bağlantı noktasının adını göreceksiniz. LXC / Docker konteynırları ile, sırasıyla /lxc/<containerid>veya benzeri bir şey /docker/<containerid>olacaktır.


13
docker artık bu yollar dockeryerine kullanıyorlxc
Andy

4
Lxd / lxc kapları için çalışmaz, ancak stackoverflow.com/a/20010626/170230 çalışır .
Draco Ater

/Systemd'ın sonraki sürümlerinde, tüm cgroups için kullanılan işlem 1'e güvenemeyeceğiniz anlaşılıyor; Benim Debian 9 sistemde on cgroups sadece üç (232 systemd) ( 3:cpuset, 4:perf_eventve 7:freezer) temelinde yer alır; gerisi altında /init.scope. Bununla birlikte, bu dosyayı aramanın şu :/docker/anda en güvenilir buluşsal yöntem olduğunu düşünüyorum .
cjs

2
grep 'docker\|lxc' /proc/1/cgroupDocker 18.09'da benim için çalışıyor.
rypel

1
Benim için çalışmıyor. Ana Ubuntu 19.04, konuk Ubuntu 18.04 LXC ayrıcalıklı kapsayıcı kullanarak. / proc / 1 / cgroup, lxc dizesini İÇERMEZ.
Gab

157

Docker, .dockerenvkapsayıcı içindeki dizin ağacının kökünde bir dosya oluşturur . Doğrulamak için bu komut dosyasını çalıştırabilirsiniz

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


DAHA FAZLA: Ubuntu aslında bir bash betiğine sahiptir: /bin/running-in-containerve aslında çağrıldığı kap tipini döndürebilir. Yine de diğer büyük dağıtımları bilmiyorum.


13
Önemli not: .dockerinitdosya Docker'ın son sürümlerinde kaldırılmıştır , bu nedenle bu yöntem artık çalışmaz. Bu yazıdan itibaren .dockerenvdosya hala korunuyor, belki de bunun yerine kullanılabilir.
Jason R

Debian /bin/running-in-containertarafından sağlanır upstart. Systemd'e geçişle ortadan kalkabilir. Umarım - kulağa yararlı geliyor!
Max Murphy

"dizin ağacının üstünde", bu ne anlama geliyor? nerede bu?
Alexander Mills

3
Diğerleri bu denetimi dikkat çekmişlerdir .dockerenvedilir önerilmemektedir
Dave

1
Not: .dockerenv testi yalnızca çalışma zamanı liman işçisi arka plan programı ise çalışır. Podman ya da başka bir şey kullanıyorsanız, bu başarısız olur.
Benjamin Kircher

22

Yeni bir ubuntu 16.04 sisteminde, yeni systemd & lxc 2.0

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

Bu benim için Ubuntu fokal 20.04 üzerinde çalışıyor. Bu noktanın üstündeki cevapların hiçbiri olmadı.
Jonathan Hartley

16

Bir bash betiğinde docker'ı kontrol etmenin kısa bir yolu:

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

14

Docker'da çalışıp çalışmadığını kontrol etmek için kullanışlı Python işlevi:

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
Önemli Not! Konteyner kubernet'lerde çalışırken bu işe yaramaz. Bunun yerine, son satırı 'liman işçisi' yerine 'kubepod' ile değiştirin. (Veya her ikisini de kontrol eden bir "veya" ifadesi koyun;))
JJC

1
Bu var kubepodssanırım.
rookie099

9

Sürecin PID'sini çıkarmak için proc çizelgesini (/ proc / $ PID / sched) kullanırız. İşlemin kapsayıcı içindeki PID'si ana bilgisayardaki PID'den (kapsayıcı olmayan bir sistem) farklı olacaktır.

Örneğin, bir kaptaki / proc / 1 / sched çıktısı aşağıdakileri döndürür:

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

Kapsayıcı olmayan bir ana makinedeyken:

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

Bu, bir kapta olup olmadığınızı ayırt etmenize yardımcı olur.


İşletim sistemine bağlı olarak, "init" in "systemd" ile değiştirilmesi gerekebilir. Burada systemd hakkında daha fazla bilgi bulabilirsiniz .
BrianV

Evet, ama nokta başlangıç ​​sürecinin adı değildi, nokta süreç numarasıydı.
MillerGeek

Bu sadece Docker üzerinde çalışıyor gibi görünüyor. LXC konteynırında Systemd PID 1
MillerGeek

Artık liman işçisinde de 1 geri dönüyor. Genellikle shve initorada değildir , ama ikisinde de hemen hemen her şey olabilir.
Jan Hudec

bash-5.0# cat /proc/1/sched bash (1, #threads: 1)
Liman

5

En kolay yol çevreyi kontrol etmektir. Eğer varsa container=lxcdeğişkeni, bir kap içinde bulunmaktadır.

Aksi takdirde, kök iseniz, gerçekleştirmeyi mknodveya mountçalışmayı deneyebilirsiniz , başarısız olursa, büyük olasılıkla bırakılan yetenekleri olan bir kaptasınız demektir.


Bu sadece docker için değil (bunu kontrol etmedi), ama daha da önemlisi, /proc/1/cgroupbunu tespit etmenize izin vermeyen lxd / lxc kapları (işaretli) için çalışır.
Draco Ater

2
yanıtı sahte kod yerine kodla düzenleyebilir misiniz? "container = lxc"? uygun bir şey değil. if [["lxc" = "$ container"]] gibi bir şey mi demek istediniz?
Alexander Mills

3
Yani ... garip, genellikle env değişkenleri tüm sınırlarda, bu yüzden burada biraz hassasiyet arıyorum
Alexander Mills

7
docker run alpine envo değişkene benzeyen bir şey vermez
Archimedes Trajano

3

Cevabım yalnızca Node.js işlemleri için geçerlidir, ancak Node.js'ye özgü bir yanıt arayan bu soruya rastlayan bazı ziyaretçiler için geçerli olabilir.

Ben de aynı sorun vardı ve sadece bu amaç için /proc/self/cgroupbir npm paketi oluşturdum - bir Node.js işlemi bir Docker kapsayıcı içinde çalışıp çalışmadığını tespit etmek için.

Konteynerle npm modülü Node.js. size yardımcı olacaktır Şu anda Io.js'de test edilmemiştir, ancak orada da çalışabilir.


Bu modül için teşekkürler, bekleyen birkaç açık düzeltme gibi görünüyor - hala bunu koruyor musunuz?
stevokk

2

Python'da yukarıdaki tüm çözümleri kontrol edin:

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

Kavramın ispatı:

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

Bu Mac tabanlı docker kapsayıcısında benim için işe yaramadı. Boş döner. Docker sürüm 2.1.0.1 (37199).
splintercell

Bu yaptı: def is_non_docker(): return os.path.exists('/proc/1/cgroup')burada kabul edilen cevaba göre stackoverflow.com/questions/20010199/…
splintercell

2
Yararsız Kedi Kullanımı Ödülü kazanırsınız. Ve Alt Sürecin Yararsız Kullanımı bir.
Jan Hudec

Evet, bu yepyeni bir gereksiz seviye cat! Güzel bir :-D
Timmmm

Haklısın, hala her şeyi kapsayan olmasa da cevabı güncelleyeceğim. @JanHudec
blakev

1

Docker her geçen gün gelişiyor, bu yüzden .dockerenv .dockerinitgelecekte de devam edip etmeyeceklerini söyleyemeyiz .

Linux lezzetlerinin çoğunda initbaşlamak için ilk süreçtir. Ancak kaplar için bu doğru değildir.

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

6
@RomanTrofimov LXC / Docker da değil. Ne komik bir yorum.
abourget

1
Centos 7'de de çalışmaz. Ana bilgisayarımda çalıştığımda docker diyor. Görünüşe göre systemd süreç kimliği 1 olarak çalışıyor
Venkateswara Rao

@VenkateswaraRao - Bu, kabın içinde çalıştırılmalıdır. Amaç, bir liman işçisi konteyneri içinde olup olmadığınızı bulmaktır.
Govind Kailas

1
@GovindKailas: Sorun şu ki, bu normal PID olanı olduğunu varsayıyor, ki bu ya da sistemlerde initdoğru değil ...systemdlaunchd
Gert van den Berg

3
@SamThomas: launchd, uptart, Solaris SMF, systemd, Sys V stili başlangıcı, BSD stili başlangıcı (bu ikisi ve diğerleri PID 1'i initolsa da diyebilirler ), OpenRC, initng, runit. Buraya bakın . Çoğu modern Linux tabanlı sistem systemd, bazı daha eski olanları kullanacaktı ... Tüm modern OS X sistemleri kullanacaktılaunchd
Gert van den Berg

0

Bu SO Soru-Cevap: "İşletim sisteminin sanal bir ortamda çalışıp çalışmadığını öğrenin" ; OP'nin sorusuyla aynı olmasa da, gerçekten hangi konteynerin içinde bulunduğunuzu (varsa) bulmak için sıkça karşılaşılan durumlara cevap verir.

Özellikle, oldukça iyi çalışıyor gibi görünen bu bash betiğinin kodunu yükleyin ve okuyun:

virt-what :

sudo apt install virt-what

İle çalışmaz virt-whatUbuntu 16.04 üzerinde sürümü 1,14-1. Düzeltme eki gerekiyor.
Lucas

0

JJC'nin cevabını ruby ​​diline çevirdim

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

Bir docker kapsayıcısında, girişler /proc/self/cgroupana bilgisayardaki gruplara bağlanır.

örneğin bir kapta

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

oysa ev sahibi için aynı

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

Düşük profil testi için kabukta bir şey kullanma

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

Her ikisinde de 1 döndürür.
sorin

-4

Belki de bu işe yarar:

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

İstediğin bu mu? Umarım yardımcı olur =)


1
dockerAçıkçası, kabın içinden hiçbir ikili mevcut değildir.
toriningen

3
Umm, bu kontrol kabının olduğu dockerve ana makinelerin docker soketine eriştiği durumlarda (örneğin gitlab docker-in-docker) başarısız olur .
shalomb

1
Evet, haklısın, elbette ^^ yok. Soru hakkında okuduğum zamanda yanlış bir yorum aldım. Teşekkürler Shalomb.
Leonardo Da Vinci
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.