Bagaimana saya bisa mendapatkan informasi kontainer Docker Linux dari dalam wadah itu sendiri?

135

Saya ingin memberitahukan docker containerskonfigurasi mereka, dengan cara yang sama Anda dapat memperoleh informasi tentang instance EC2 melalui metadata.

Saya bisa menggunakan (asalkan dockermendengarkan di port 4243)

curl http://172.17.42.1:4243/containers/$HOSTNAME/json

untuk mendapatkan beberapa datanya, tetapi ingin tahu apakah ada cara yang lebih baik setidaknya mendapatkan ID lengkap wadah, karena HOSTNAMEsebenarnya disingkat menjadi 12 karakter dan buruh pelabuhan tampaknya melakukan "pertandingan terbaik" di atasnya.

Juga, bagaimana saya bisa mendapatkan IP eksternal dari host buruh pelabuhan (selain mengakses metadata EC2, yang khusus untuk AWS)

Alessandro
sumber
2
WASPADALAH: Anda harus membaca lvh.io/posts/… ini sebelum mencoba salah satu pendekatan di bawah ini yang mencoba menggunakan /var/run/docker.sock di dalam wadah
harschware
1
Jika tautan @ harschware terputus, saya akan meringkas di sini: Dengan memberikan akses ke wadah /var/run/docker.sock, dimungkinkan (sepele) untuk keluar dari kontainmen yang disediakan oleh buruh pelabuhan dan mendapatkan akses ke mesin host. Jelas ini berpotensi berbahaya.
John
1
Adakah yang tahu cara mendapatkan informasi yang sama di windows docker container jika argumen --hostname digunakan dengan perintah run sehingga menjalankan 'hostname' tidak lagi memberi Anda containerid?
Timothy John Laird

Jawaban:

68

Saya menemukan bahwa id kontainer dapat ditemukan di / proc / self / cgroup

Jadi Anda bisa mendapatkan id dengan:

cat /proc/self/cgroup | grep -o  -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"
Thomas A.
sumber
15
Harus sedikit men-tweak, ini bekerja untuk saya di Docker 1.4.1 cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
ICas
5
Untuk buruh pelabuhan 1.6.2 saya harus menggunakan:cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1
Jay Taylor
14
Aaaaand Docker 1.12:cat /proc/1/cgroup | grep 'docker/' | tail -1 | sed 's/^.*\///' | cut -c 1-12
smets.kevin
24
Saya agak suka basename "$(cat /proc/1/cpuset)"danbasename "$(head /proc/1/cgroup)"
madeddie
3
Di masa depan, jika namespace cgroup dan cgroup v2 digunakan di buruh pelabuhan, metode ini mungkin tidak berfungsi lagi.
Jing Qiu
69

Kecuali dikesampingkan, nama host tampaknya menjadi id penampung pendek di Docker 1.12

root@d2258e6dec11:/project# cat /etc/hostname
d2258e6dec11

Secara eksternal

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED                 STATUS                      PORTS               NAMES
d2258e6dec11        300518d26271        "bash"              5 minutes ago       

$ docker -v
Docker version 1.12.0, build 8eab29e, experimental
ardochhigh
sumber
4
Yup ini membuatnya mudah untuk menarik info di nodejs untuk saya. const os = require('os'); console.log(os.hostname());
pulkitsinghal
2
Untuk mendapatkan nama host yang cocok dengan ID Kontainer di Jawa, gunakan InetAddress.getLocalHost().getHostName().
Nathan
2
Terkadang lebih mudah untuk membaca nilai variabel lingkungan $HOSTNAME(misalnya dalam skrip shell).
Faheel
34

Anda dapat berkomunikasi dengan buruh pelabuhan dari dalam wadah menggunakan soket unix melalui Docker Remote API:

https://docs.docker.com/engine/reference/api/docker_remote_api/

Dalam sebuah wadah, Anda dapat menemukan id buruh pelabuhan yang dipersingkat dengan memeriksa $HOSTNAMEenv var. Menurut dokter, ada sedikit kemungkinan tabrakan, saya pikir untuk sejumlah kecil kontainer, Anda tidak perlu khawatir. Saya tidak tahu cara mendapatkan id lengkap secara langsung.

Anda dapat memeriksa wadah dengan cara yang sama seperti diuraikan dalam jawaban beringin :

GET /containers/4abbef615af7/json HTTP/1.1

Tanggapan:

HTTP/1.1 200 OK
Content-Type: application/json

{
         "Id": "4abbef615af7......  ",
         "Created": "2013.....",
         ...
}

Atau, Anda dapat mentransfer nomor buruh pelabuhan ke wadah dalam file. File ini terletak di "volume terpasang" sehingga dipindahkan ke wadah:

docker run -t -i -cidfile /mydir/host1.txt -v /mydir:/mydir ubuntu /bin/bash

Id buruh pelabuhan (disingkat) akan berada di file / mydir/host1.txt dalam wadah.

Jiri
sumber
2
Terima kasih tetapi ini adalah pendekatan yang sama yang saya gunakan, dan akan rusak jika Anda menetapkan nama host dengan -h ketika Anda menjalankan buruh pelabuhan.
Alessandro
@Alessandro Saya telah menambahkan informasi tentang parameter -cidfile untuk menjalankan buruh pelabuhan. Ini dapat membantu Anda untuk mengirimkan nomor buruh pelabuhan ke wadah alih-alih menggunakan $ HOSTNAME.
Jiri
Bagus! Ya itu adalah sesuatu yang bisa saya gunakan! Terima kasih!
Alessandro
Anehnya, di 1.11.2 sepertinya envtidak daftar HOSTNAME, tetapi echo $HOSTNAMEberfungsi.
Jesse Glick
Ini tidak berfungsi sama sekali, dan URL Anda rusak dan sekarang dialihkan ke dokumentasi yang salah. requests.exceptions.MissingSchema: Invalid URL '/containers/1d26a841bf07/json': No schema supplied. Perhaps you meant http:///containers/1d26a841bf07/json?
Cerin
24

Ini akan mendapatkan id kontainer lengkap dari dalam sebuah wadah:

cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g'
Tawanan
sumber
22

Sebuah komentar oleh madeddie terlihat paling elegan bagi saya:

CID=$(basename $(cat /proc/1/cpuset))
sirex
sumber
21

PERINGATAN: Anda harus memahami risiko keamanan dari metode ini sebelum Anda mempertimbangkannya. Ringkasan risiko John :

Dengan memberikan wadah akses ke /var/run/docker.sock, [mudah sepele] untuk keluar dari kontainmen yang disediakan oleh buruh pelabuhan dan mendapatkan akses ke mesin host. Jelas ini berpotensi berbahaya.


Di dalam wadah, dockerId adalah nama host Anda. Jadi, Anda bisa:

  • instal paket docker-io dalam wadah Anda dengan versi yang sama dengan host
  • mulai dengan --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • Akhirnya, jalankan: docker inspect $(hostname)di dalam wadah

Hindari ini. Lakukan saja jika Anda memahami risikonya dan memiliki mitigasi risiko yang jelas.

Omar Marquez
sumber
1
Saya menduga ini tidak akan berfungsi jika opsi buruh pelabuhan --hostnametelah digunakan.
hairyhenderson
Jika --hostnamediatur, Anda dapat menggunakan kombinasi dari jawaban ini dan komentar dari @ Jay Taylor dalam jawaban yang diterima: docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1)untuk mendapatkan semua informasi tentang wadah yang sedang berjalan.
Michael K.
Bisakah Anda menaruh referensi ke docker-io?
Brad P.
Saya menganggap npmjs.com/package/docker-io, tapi itu yang dikatakan Google dan mungkin bukan yang Anda maksud.
Brad P.
15

Untuk membuatnya sederhana,

  1. ID Kontainer adalah nama host Anda di dalam buruh pelabuhan
  2. Informasi kontainer tersedia di dalam / proc / self / cgroup

Untuk mendapatkan nama host,

hostname

atau

uname -n

atau

cat /etc/host

Keluaran dapat diarahkan ke file apa saja & dibaca kembali dari aplikasi. Mis: # hostname > /usr/src//hostname.txt

Tejas jain
sumber
10

Saya telah menemukan bahwa di 17.09 ada cara paling sederhana untuk melakukannya di dalam wadah buruh pelabuhan:

$ cat /proc/self/cgroup | head -n 1 | cut -d '/' -f3
4de1c09d3f1979147cd5672571b69abec03d606afcc7bdc54ddb2b69dec3861c

Atau seperti yang sudah diberitahukan, versi yang lebih pendek dengan

$ cat /etc/hostname
4de1c09d3f19

Atau sederhananya:

$ hostname
4de1c09d3f19
Adrian Antunez
sumber
6

Docker secara default menetapkan nama host ke ID wadah, tetapi pengguna dapat menimpanya --hostname. Sebagai gantinya, periksa /proc:

$ more /proc/self/cgroup
14:name=systemd:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
13:pids:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
12:hugetlb:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
11:net_prio:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
10:perf_event:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
9:net_cls:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
8:freezer:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
7:devices:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
6:memory:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
5:blkio:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
4:cpuacct:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
3:cpu:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
2:cpuset:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
1:name=openrc:/docker

Berikut ini adalah satu-liner berguna untuk mengekstrak ID wadah:

$ grep "memory:/" < /proc/self/cgroup | sed 's|.*/||'
7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
Wilfred Hughes
sumber
2

Anda dapat menggunakan baris perintah ini untuk mengidentifikasi ID kontainer saat ini (diuji dengan buruh pelabuhan 1.9).

awk -F"-|/." '/1:/ {print $3}' /proc/self/cgroup

Kemudian, sedikit permintaan ke Docker API (Anda dapat membagikan /var/run/docker.sock) untuk mengambil semua informasi.

Baptiste Donaux
sumber
1
awk -F "- | /." '/ 1: / {print $ 3}' / proc / self / cgroup
usil
2

Beberapa solusi yang diposting telah berhenti berfungsi karena perubahan format /proc/self/cgroup. Ini adalah satu perintah grep GNU yang seharusnya sedikit lebih kuat untuk memformat perubahan:

grep -o -P -m1 'docker.*\K[0-9a-f]{64,}' /proc/self/cgroup

Untuk referensi, berikut adalah potongan dari / proc / self / cgroup dari container docker dalam yang telah diuji dengan perintah ini:

Linux 4.4:

11:pids:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope
...
1:name=systemd:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope

Linux 4.8 - 4.13:

11:hugetlb:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013
...
1:name=systemd:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013
kanaka
sumber
1
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup
Andrew Wolfe
sumber
0

Sebagai tambahan, jika Anda memiliki pid dari wadah dan ingin mendapatkan buruh pelabuhan dari wadah itu, cara yang baik adalah menggunakan nsenter dalam kombinasi dengan sihir sed di atas:

nsenter -n -m -t pid -- cat /proc/1/cgroup | grep -o -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"

anbhat
sumber
-19

Gunakan docker inspect.

$ docker ps # get conteiner id
$ docker inspect 4abbef615af7
[{
    "ID": "4abbef615af780f24991ccdca946cd50d2422e75f53fb15f578e14167c365989",
    "Created": "2014-01-08T07:13:32.765612597Z",
    "Path": "/bin/bash",
    "Args": [
        "-c",
        "/start web"
    ],
    "Config": {
        "Hostname": "4abbef615af7",
...

Bisa mendapatkan ip sebagai berikut.

$ docker inspect -format="{{ .NetworkSettings.IPAddress }}" 2a5624c52119
172.17.0.24
beringin
sumber
5
Bukan itu yang saya maksud. Saya harus bisa mendapatkan informasi ini dari dalam wadah. Apakah pada dasarnya saya perlu cara untuk memahami ID wadah yang saya jalankan dari dalam.
Alessandro