ฉันจะรับข้อมูลคอนเทนเนอร์ Docker Linux จากภายในคอนเทนเนอร์ได้อย่างไร


135

ฉันต้องการแจ้งให้docker containersทราบถึงการกำหนดค่าเช่นเดียวกับที่คุณสามารถรับข้อมูลเกี่ยวกับอินสแตนซ์ EC2 ผ่านข้อมูลเมตา

ฉันสามารถใช้ได้ (ให้มาdockerคือการฟังบนพอร์ต4243)

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

เพื่อรับข้อมูลบางส่วน แต่ต้องการทราบว่ามีวิธีที่ดีกว่าอย่างน้อยที่สุดในการรับ ID เต็มของคอนเทนเนอร์หรือไม่เพราะHOSTNAMEจริงๆแล้วสั้นลงเหลือ 12 อักขระและนักเทียบท่าดูเหมือนจะทำงานได้ "ตรงที่สุด"

นอกจากนี้ฉันจะรับ IP ภายนอกของโฮสต์นักเทียบท่าได้อย่างไร (นอกเหนือจากการเข้าถึงข้อมูลเมตาของ EC2 ซึ่งเป็นข้อมูลเฉพาะสำหรับ AWS)


2
ระวัง: คุณควรอ่านlvh.io/posts/…นี้ก่อนที่จะลองใช้วิธีการใด ๆ ด้านล่างที่พยายามใช้ /var/run/docker.sock ภายในคอนเทนเนอร์
harschware

1
ในกรณีที่ลิงก์ของ @ harschware แตกฉันจะสรุปที่นี่: โดยการให้การเข้าถึงคอนเทนเนอร์/var/run/docker.sockเป็นไปได้ (เล็กน้อย) ที่จะแยกออกจากการกักกันที่นักเทียบท่าจัดเตรียมไว้และเข้าถึงเครื่องโฮสต์ได้ เห็นได้ชัดว่าสิ่งนี้อาจเป็นอันตราย
John

1
ไม่มีใครรู้วิธีรับข้อมูลเดียวกันในwindows docker container ถ้าอาร์กิวเมนต์ --hostname ถูกใช้กับคำสั่ง run ดังนั้นการเรียกใช้ 'hostname' จะไม่ให้ containerid แก่คุณอีกต่อไป?
Timothy John Laird

คำตอบ:


68

ฉันพบว่า ID คอนเทนเนอร์สามารถพบได้ใน / proc / self / cgroup

ดังนั้นคุณจะได้รับรหัสด้วย:

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

15
ต้องปรับแต่งเล็กน้อยสิ่งนี้ใช้ได้กับฉันใน Docker 1.4.1 cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
ICas

5
สำหรับนักเทียบท่า 1.6.2 ฉันต้องใช้: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
ฉันชอบbasename "$(cat /proc/1/cpuset)"และbasename "$(head /proc/1/cgroup)"
madeddie

3
ในอนาคตหากใช้เนมสเปซ cgroup และ cgroup v2 ในนักเทียบท่าวิธีนี้อาจใช้ไม่ได้อีกต่อไป
Jing Qiu

69

ชื่อโฮสต์ดูเหมือนจะเป็นรหัสคอนเทนเนอร์แบบสั้นใน Docker 1.12 เว้นแต่จะถูกแทนที่

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

อย่างผิวเผิน

$ 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

4
ใช่สิ่งนี้ทำให้ง่ายต่อการดึงข้อมูลใน nodejs สำหรับฉัน const os = require('os'); console.log(os.hostname());
pulkitsinghal

2
ที่จะได้รับชื่อโฮสต์ที่ตรงกับรหัสคอนเทนเนอร์ใน Java InetAddress.getLocalHost().getHostName()ใช้
นาธา

2
บางครั้งการอ่านค่าของตัวแปรสภาพแวดล้อมจะง่ายกว่า$HOSTNAME(เช่นในเชลล์สคริปต์)
Faheel

34

คุณสามารถสื่อสารกับนักเทียบท่าจากภายในคอนเทนเนอร์โดยใช้ซ็อกเก็ต Unix ผ่าน Docker Remote API:

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

ในคอนเทนเนอร์คุณสามารถค้นหารหัสนักเทียบท่าแบบย่อได้โดยการตรวจสอบ$HOSTNAMEenv var ตามเอกสารมีโอกาสน้อยที่จะชนกันฉันคิดว่าสำหรับคอนเทนเนอร์จำนวนน้อยคุณไม่ต้องกังวลเกี่ยวกับเรื่องนี้ ไม่ทราบวิธีรับ id เต็มโดยตรง

คุณสามารถตรวจสอบคอนเทนเนอร์ในลักษณะเดียวกับที่ระบุไว้ในคำตอบบันยัน

GET /containers/4abbef615af7/json HTTP/1.1

การตอบสนอง:

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

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

หรือคุณสามารถถ่ายโอน id นักเทียบท่าไปยังคอนเทนเนอร์ในไฟล์ ไฟล์อยู่บน "วอลุ่มที่ติดตั้ง" ดังนั้นจึงถูกถ่ายโอนไปยังคอนเทนเนอร์:

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

ID นักเทียบท่า (แบบย่อ) จะอยู่ในไฟล์ /mydir/host1.txt ในคอนเทนเนอร์


2
ขอบคุณ แต่นี่เป็นวิธีเดียวกับที่ฉันใช้อยู่และจะพังถ้าคุณตั้งชื่อโฮสต์ด้วย -h เมื่อคุณเรียกใช้นักเทียบท่า
Alessandro

@Alessandro ฉันได้เพิ่มข้อมูลเกี่ยวกับพารามิเตอร์ -cidfile ให้กับนักเทียบท่าแล้ว อาจช่วยให้คุณส่งรหัสนักเทียบท่าไปยังคอนเทนเนอร์แทนที่จะใช้ $ HOSTNAME
Jiri

ที่ดี! ใช่นั่นคือสิ่งที่ฉันสามารถใช้ได้! ขอบคุณ!
Alessandro

ผิดปกติใน 1.11.2 ดูเหมือนenvจะไม่แสดงรายการHOSTNAMEแต่ใช้echo $HOSTNAMEงานได้
Jesse Glick

วิธีนี้ใช้ไม่ได้ผลและ URL ของคุณใช้งานไม่ได้และตอนนี้เปลี่ยนเส้นทางไปยังเอกสารที่ไม่ถูกต้อง requests.exceptions.MissingSchema: Invalid URL '/containers/1d26a841bf07/json': No schema supplied. Perhaps you meant http:///containers/1d26a841bf07/json?
Cerin

24

สิ่งนี้จะได้รับ ID คอนเทนเนอร์แบบเต็มจากภายในคอนเทนเนอร์:

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


21

คำเตือน:คุณควรเข้าใจความเสี่ยงด้านความปลอดภัยของวิธีนี้ก่อนที่จะพิจารณา บทสรุปของจอห์นเกี่ยวกับความเสี่ยง:

การให้คอนเทนเนอร์เข้าถึง/var/run/docker.sockมันเป็นเรื่องง่าย [เล็กน้อย] ที่จะแยกออกจากที่กักกันที่นักเทียบท่าจัดเตรียมไว้และเข้าถึงเครื่องโฮสต์ได้ เห็นได้ชัดว่าสิ่งนี้อาจเป็นอันตราย


ภายในคอนเทนเนอร์ dockerId คือชื่อโฮสต์ของคุณ คุณสามารถ:

  • ติดตั้งแพ็คเกจ docker-ioในคอนเทนเนอร์ของคุณด้วยเวอร์ชันเดียวกับโฮสต์
  • เริ่มต้นด้วย --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • สุดท้ายเรียกใช้: docker inspect $(hostname)ภายในคอนเทนเนอร์

หลีกเลี่ยงสิ่งนี้ ทำได้ก็ต่อเมื่อคุณเข้าใจความเสี่ยงและมีการบรรเทาความเสี่ยงที่ชัดเจน


1
ฉันสงสัยว่าจะใช้ไม่ได้หากมีการใช้--hostnameตัวเลือกdocker run
hairyhenderson

หาก--hostnameตั้งค่าไว้คุณสามารถใช้ชุดค่าผสมจากคำตอบนี้และความคิดเห็นจาก @Jay Taylor ในคำตอบที่ยอมรับ: docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1)เพื่อรับข้อมูลทั้งหมดเกี่ยวกับคอนเทนเนอร์ที่กำลังทำงานอยู่
Michael K.

คุณช่วยอ้างอิงถึง docker-io ได้ไหม
Brad P.

ฉันคิดว่ามันเป็นnpmjs.com/package/docker-ioแต่นั่นเป็นเพียงสิ่งที่ Google บอกฉันและอาจไม่ใช่สิ่งที่คุณหมายถึง
Brad P.

15

เพื่อให้ง่าย

  1. Container ID คือชื่อโฮสต์ของคุณใน Docker
  2. ข้อมูลคอนเทนเนอร์อยู่ใน / proc / self / cgroup

หากต้องการรับชื่อโฮสต์

hostname

หรือ

uname -n

หรือ

cat /etc/host

เอาต์พุตสามารถเปลี่ยนเส้นทางไปยังไฟล์ใดก็ได้และอ่านกลับจากแอปพลิเคชันเช่น: # hostname > /usr/src//hostname.txt


10

ฉันพบว่าใน 17.09 มีวิธีที่ง่ายที่สุดในการทำภายในคอนเทนเนอร์นักเทียบท่า:

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

หรืออย่างที่บอกไปแล้วรุ่นสั้นกว่าด้วย

$ cat /etc/hostname
4de1c09d3f19

หรือเพียงแค่:

$ hostname
4de1c09d3f19

6

นักเทียบท่าตั้งชื่อโฮสต์เป็น ID คอนเทนเนอร์ตามค่าเริ่มต้น แต่ผู้ใช้สามารถแทนที่สิ่งนี้ด้วย--hostname. ให้ตรวจสอบแทน/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

นี่คือหนึ่งซับที่สะดวกในการแยก ID คอนเทนเนอร์:

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

2

คุณสามารถใช้บรรทัดคำสั่งนี้เพื่อระบุ ID คอนเทนเนอร์ปัจจุบัน (ทดสอบด้วยนักเทียบท่า 1.9)

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

จากนั้นขอ Docker API เล็กน้อย (คุณสามารถแชร์ /var/run/docker.sock) เพื่อดึงข้อมูลทั้งหมด


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

2

โซลูชันที่โพสต์บางรายการหยุดทำงานเนื่องจากมีการเปลี่ยนแปลงรูปแบบของไฟล์/proc/self/cgroup. นี่คือคำสั่ง grep GNU เดียวที่ควรจะมีประสิทธิภาพมากขึ้นในการเปลี่ยนแปลงรูปแบบ:

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

สำหรับการอ้างอิงนี่คือตัวอย่างของ / proc / self / cgroup จากภายในคอนเทนเนอร์นักเทียบท่าที่ผ่านการทดสอบด้วยคำสั่งนี้:

ลินุกซ์ 4.4:

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

ลินุกซ์ 4.8 - 4.13:

11:hugetlb:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013
...
1:name=systemd:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013


0

นอกจากนี้หากคุณมี pid ของคอนเทนเนอร์และต้องการรับรหัสนักเทียบท่าของคอนเทนเนอร์นั้นวิธีที่ดีคือใช้ nsenter ร่วมกับเวทมนตร์ด้านบน:

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


-19

ใช้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",
...

ได้ ip ดังนี้.

$ docker inspect -format="{{ .NetworkSettings.IPAddress }}" 2a5624c52119
172.17.0.24

5
นี่ไม่ใช่สิ่งที่ฉันหมายถึง ฉันต้องสามารถรับข้อมูลนี้จากในคอนเทนเนอร์ได้ โดยพื้นฐานแล้วฉันต้องการวิธีทำความเข้าใจ ID ของคอนเทนเนอร์ที่ฉันกำลังเรียกใช้จากภายใน
Alessandro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.