ฉันจะดีบักการกำหนดค่าเริ่มต้นคอนเทนเนอร์ของนักเทียบท่าได้อย่างไร


93

ฉันมีปัญหากับคอนเทนเนอร์ถึงแม้ว่ามันจะสร้างขึ้นอย่างสมบูรณ์แบบ แต่ก็ไม่เริ่มต้นอย่างถูกต้อง สาเหตุเป็นวิธีแก้ปัญหาที่ฉันเพิ่มลงใน Dockerfile (สำหรับการกำหนดเส้นทาง / etc / hosts กำหนดเอง)

RUN mkdir -p -- /lib-override /etc-override && cp /lib/libnss_files.so.2 /lib-override
ADD hosts.template /etc-override/hosts
RUN perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override

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

$ docker run image ls
usr bin ...

แต่นี่ไม่ใช่:

$ docker run image ls -l
$

ไม่มีอะไรในบันทึกและฉันไม่สามารถเรียกเชลล์แบบโต้ตอบได้ ฉันสามารถใช้สเตรซเพื่อดูว่าเกิดอะไรขึ้น แต่ฉันหวังว่าจะมีวิธีที่ดีกว่านี้

มีวิธีใดบ้างที่ฉันสามารถกำหนดให้นักเทียบท่าเป็น verbose มากขึ้น?

แก้ไข : ขอบคุณ Andrew D. ตอนนี้ฉันรู้ว่ามีอะไรผิดปกติกับรหัสข้างต้น (ฉันทิ้งไว้เพื่อให้สามารถเข้าใจคำตอบของเขา) ตอนนี้ปัญหายังคงเป็นอย่างไรฉันจะแก้ไขข้อบกพร่องบางอย่างเช่นนี้หรือได้รับบางส่วนที่ทำไมls -lล้มเหลวทำไมlsไม่ได้

แก้ไข : -D = จริงอาจให้ผลผลิตมากขึ้น แต่ไม่ได้อยู่ในกรณีของฉัน ...


โปรดใช้ความพยายามในการทำเครื่องหมายคำตอบอย่างใดอย่างหนึ่งว่า "ยอมรับ" ขอบคุณ!
Brian Topping

คำตอบ:


95

eventsคำสั่งDocker อาจช่วยได้และคำสั่งDocker logsสามารถดึงบันทึกได้แม้ว่าภาพจะเริ่มไม่สำเร็จ

เริ่มแรกdocker eventsในพื้นหลังเพื่อดูว่าเกิดอะไรขึ้น

docker events&

จากนั้นรันdocker run ...คำสั่งที่ล้มเหลวของคุณ จากนั้นคุณควรเห็นสิ่งต่อไปนี้บนหน้าจอ:

2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die

จากนั้นคุณจะได้รับ hex id เริ่มต้นจากข้อความก่อนหน้าหรือผลลัพธ์ของคำสั่งเรียกใช้ จากนั้นคุณสามารถใช้กับคำสั่งบันทึก:

docker logs <copy the instance id from docker events messages on screen>

ตอนนี้คุณควรเห็นผลลัพธ์บางส่วนจากการเริ่มต้นรูปภาพที่ล้มเหลว

ตามที่ @alexkb แนะนำไว้ในความคิดเห็น: docker events&อาจลำบากถ้าคอนเทนเนอร์ของคุณถูกรีสตาร์ทอย่างต่อเนื่องจากบริการ AWS ECS ในสถานการณ์นี้มันอาจจะง่ายกว่าที่จะเอาเลขฐานสิบหกคอนเทนเนอร์ออกจากการเข้า/var/log/ecs/ecs-agent.log.<DATE>สู่ระบบ logs <hex id>จากนั้นใช้นักเทียบท่า


มีประโยชน์มาก! ใหม่สำหรับนักเทียบท่าและกำลังพยายามให้ตัวยึดทำงานอยู่ แก้ไขด้วยขั้นตอนการดีบักเหล่านี้ พบคนใน Medium.com ที่มีปัญหาเดียวกัน: medium.com/@jameson_37151/…
Jameson

ฉันได้รับ "ไม่พบที่เก็บ"!?
Hedgehog สมองเสื่อม

แปลก. เพียงเพื่อให้แน่ใจว่า @dehedhedgehog คุณลองคัดลอก hex-id จากข้อความบันทึกที่ลงท้ายด้วย " (from xxx/xxx:latest) die" หรือไม่?
Peter Lamberg

1
ขอบคุณคำตอบนี้มากมันเป็นตัวช่วยชีวิต สิ่งเดียวที่ต้องเพิ่มคือdocker events&สามารถสร้างปัญหาได้หากคอนเทนเนอร์ของคุณถูกรีสตาร์ทอย่างต่อเนื่องจากบริการ AWS ECS /var/log/ecs/ecs-agent.log.<DATE>ดังนั้นในสถานการณ์นี้มันอาจจะง่ายที่จะได้รับรหัสฐานสิบหกภาชนะออกจากบันทึกใน จากนั้นใช้docker logs <hex id>ตามคำแนะนำนี้เพื่อดูว่าทำไมสิ่งต่าง ๆ ถึงไม่เริ่มระบบ
alexkb

1
@alexkb ขอบคุณ! ฉันเพิ่มข้อเสนอแนะของคุณในตอนท้ายของคำตอบเพื่อให้ผู้อื่นสามารถค้นหาได้ง่ายขึ้น
Peter Lamberg

18

สิ่งที่ดีที่สุดที่ฉันค้นพบคือ:

#stop the current demon and start it in debug modus
sudo service docker stop
dockerd -D # --debug

เพียงแค่เริ่มไคลเอนต์จากเชลล์ใหม่ ความเข้าใจผิดคือการคิดว่าลูกค้าทำอะไรจริง ๆ เลย ... ก็แค่สื่อสารกับ daemon ดังนั้นคุณไม่ต้องการดีบักไคลเอ็นต์ แต่ daemon เอง (ปกติ)


13

ในกรณีของฉัน-aแฟล็ก (แนบกับ STDOUT / STDERR) ก็เพียงพอแล้ว:

user@machine:~$ docker start -a server_name
Error: The directory named as part of the path /log/log_path/app.log does not exist.
For help, use /usr/bin/supervisord -h

มันแสดงให้เห็นข้อผิดพลาดในการเริ่มต้น (ในกรณีของเราเป็นเส้นทางบันทึกที่ขาดหายไปที่ใช้supervisord) ฉันถือว่าข้อผิดพลาดในการเริ่มต้นคอนเทนเนอร์ส่วนใหญ่จะปรากฏที่นี่เช่นกัน


3

ฉันไม่สามารถตอบคำถามของคุณเกี่ยวกับวิธีทำให้เอาต์พุตนักเทียบท่าสมบูรณ์มากขึ้น แต่ฉันสามารถบอกคุณได้ว่าการแทนที่ regex แบบแทนที่สตริงในไฟล์. so ค่อนข้างบ้าคลั่ง: สตริงมีการจัดสรรพื้นที่มากเท่านั้นและ หากคุณเปลี่ยนออฟเซ็ตไฟล์ของรายการอื่นไฟล์ elf จะเสียหาย ลองเรียกใช้ objdump หรือ readelf บนไฟล์. so ของคุณหลังจากรันคำสั่ง perl ( ก่อนที่จะเปลี่ยน LD_LIBRARY_PATH ) นอกคอนเทนเนอร์ - ดอลลาร์เพื่อให้โดนัทเสียหาย

เหตุผลที่ทำงานในการแฮ็คที่จำเป็นอย่างน่าเศร้านี้เพราะ "tmp" และ "etc" มีความยาวสายอักขระเดียวกันดังนั้นจึงไม่มีการเปลี่ยนแปลงออฟเซ็ต พิจารณาไดเรกทอรี / dkr หรือคล้ายกันถ้าคุณไม่ต้องการใช้ / tmp

หากคุณต้องใช้วิธีการนี้และเส้นทางที่คุณต้องการไม่สามารถเปลี่ยนแปลงได้ให้สร้างไลบรารีขึ้นใหม่และเปลี่ยนเส้นทางเริ่มต้นสำหรับ / etc / hosts ในแหล่งที่มา หรือดีกว่าเมื่อสร้างlibnss_files.soชื่อที่ปรับเปลี่ยนแล้วของคุณให้เป็นสิ่งที่ชอบlibnss_altfiles.soและเปลี่ยนnsswitch.confไปใช้hosts: altfilesเมื่อเริ่มต้นคอนเทนเนอร์นักเทียบท่าของคุณ (ยกเว้นว่านักเทียบท่าได้ผูกเมาท์ไว้กับ nsswitch.conf แล้วคุณจะไม่สามารถเปลี่ยนแปลงได้) สิ่งนี้จะช่วยให้คุณมี libnss_altfiles.so ขนานกับไลบรารีปกติของคุณในระบบพื้นฐาน หากนักเทียบท่าทำ bind-mount nsswitch.conf ให้ปล่อยสำเนาของ libnss_files.so ที่สร้างใหม่ของคุณไว้ในไดเรกทอรี / lib-override ของคุณพร้อมที่จะโหลดโดย LD_LIBRARY_PATH

ในฐานะที่เป็นหัวขึ้น suid / sgid ไบนารีละเว้น LD_LIBRARY_PATH และ LD_PRELOAD ดังนั้นบางสิ่งจะพัง (อ่าน: กลับไปใช้ค่าเริ่มต้น / etc / hosts) หากคุณใช้ตัวแปรเหล่านั้น


ขอบคุณมากสำหรับข้อมูลเชิงลึกที่ยอดเยี่ยม ... ฉันเร็วเกินไปและดูว่าเกิดอะไรขึ้น ผมก็ยังไม่ทราบว่าทำไมได้รับสถิติความต้องการที่จะแก้ไขโฮสต์ (คำสั่ง ls -l) ในขณะที่รายชื่อแฟ้มอย่างง่าย (แอลเอ) ไม่ได้ ...
estani

0

ในบางครั้งคุณสามารถค้นหาข้อความแสดงข้อผิดพลาดที่มีประโยชน์โดยการ sshing เข้าสู่โหนดที่เรียกใช้ docker daemon จากนั้นทำดังนี้:

$ tail -f /var/log/containers/* /var/log/docker.log 2>&1

ใน 'Docker Community edition' บน Mac OS คุณสามารถเชื่อมต่อกับ Docker vm ได้โดยทำดังนี้

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.