วิธีเริ่มคอนเทนเนอร์ Docker ที่หยุดทำงานด้วยคำสั่งอื่น


251

ฉันต้องการเริ่มต้นนักเทียบท่าคอนเทนเนอร์ที่หยุดด้วยคำสั่งอื่นเนื่องจากคำสั่งเริ่มต้นขัดข้อง - หมายความว่าฉันไม่สามารถเริ่มคอนเทนเนอร์แล้วใช้ 'นักเทียบท่า exec'

โดยทั่วไปฉันต้องการเริ่มเปลือกเพื่อให้ฉันสามารถตรวจสอบเนื้อหาของภาชนะ

โชคดีที่ฉันสร้างคอนเทนเนอร์ด้วยตัวเลือก -it!

คำตอบ:


380

ค้นหา ID คอนเทนเนอร์ที่หยุดของคุณ

docker ps -a

กระทำคอนเทนเนอร์ที่หยุด:

คำสั่งนี้บันทึกสถานะคอนเทนเนอร์ที่ปรับเปลี่ยนเป็นรูปภาพใหม่ user/test_image

docker commit $CONTAINER_ID user/test_image

เริ่ม / เรียกใช้ด้วยจุดเข้าใช้งานอื่น:

docker run -ti --entrypoint=sh user/test_image

คำอธิบายอาร์กิวเมนต์ Entrypoint: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

บันทึก:

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

ขั้นตอนในการเริ่มต้นคอนเทนเนอร์ที่หยุดถูกยืมมาจากที่นี่: (ความคิดเห็นล่าสุด) https://github.com/docker/docker/issues/18078


1
ไม่รูปภาพเป็นแบบอ่านอย่างเดียว มันช่วยประหยัดสถานะภาชนะที่ปรับเปลี่ยนเป็นภาพใหม่ test_image
Dmitriusan

4
พลาดท่านี้เกือบทั้งหมดเกี่ยวกับการตั้งค่า env ปริมาณ UID ... ทั้งหมดก็มีเหมือนกันกับภาชนะหยุดเป็นระบบแฟ้ม (ซึ่งอาจจะเพียงพอสำหรับบางคน)
ฟลอเรียนไคลน์

4
มันจะดีถ้าฉันจะได้รับสภาพแวดล้อมเดียวกันการกำหนดค่าเครือข่ายปริมาณที่แนบมา เป็นไปได้ไหมที่จะแปลงinspectเอาต์พุตเป็นคอนฟิกูเรชันที่ใช้กับการรันครั้งต่อไป?
Otheus

2
@ Webman ใช่ แต่นั่นไม่เป็นความจริงสำหรับโวลุ่มที่ติดตั้งก่อนที่จะหยุดคอนเทนเนอร์ คุณจะต้องแนบวอลุ่มเดียวกันอย่างชัดเจนเมื่อคุณเริ่มต้นคอนเทนเนอร์ในครั้งถัดไป
Dmitriusan

1
@ EmreTapcıฉันคิดว่าการทำเช่นนั้นขัดต่ออุดมการณ์นักเทียบท่า ภาชนะบรรจุมีวัตถุประสงค์เพื่อเป็นกิจการใช้แล้วโยนทิ้งในทางตรงกันข้ามกับเครื่องเสมือน คุณอาจลองทำตามคำตอบaaa90210แต่อาจเป็นการแฮ็ค
Dmitriusan

126

แก้ไขไฟล์นี้ (ที่สอดคล้องกับที่เก็บของคุณหยุด):

vi /var/lib/docker/containers/923...4f6/config.json

เปลี่ยนพารามิเตอร์ "Path" เพื่อชี้ไปที่คำสั่งใหม่ของคุณเช่น / bin / bash คุณอาจตั้งค่าพารามิเตอร์ "Args" เพื่อส่งผ่านอาร์กิวเมนต์ไปยังคำสั่ง

รีสตาร์ทบริการตัวเทียบท่า (หมายเหตุนี่จะหยุดการทำงานของคอนเทนเนอร์ทั้งหมด):

service docker restart

แสดงรายการคอนเทนเนอร์ของคุณและตรวจสอบให้แน่ใจว่าคำสั่งเปลี่ยนไป:

docker ps -a

เริ่มภาชนะและแนบมันตอนนี้คุณควรจะอยู่ในเปลือกของคุณ!

docker start -ai mad_brattain

ทำงานกับ Fedora 22 โดยใช้ Docker 1.7.1

หมายเหตุ:หากเชลล์ของคุณไม่ทำงาน (เช่นคุณไม่ได้สร้างคอนเทนเนอร์ดั้งเดิมด้วยตัวเลือก - มัน) คุณสามารถเปลี่ยนคำสั่งเป็น "/ bin / sleep 600" หรือ "/ bin / tail -f / dev / null" แทน เพื่อให้คุณมีเวลามากพอที่จะทำ "docker exec -it CONTID / bin / bash" เป็นอีกวิธีหนึ่งในการรับเชลล์

NOTE2:นักเทียบท่าเวอร์ชันใหม่กว่ามี config.v2.json ซึ่งคุณจะต้องเปลี่ยน Entrypoint หรือ Cmd (ขอบคุณผู้ใช้ 60561)


44
ดวงตาของฉัน. ดวงตาของฉัน. ฉันหวังว่านี่เป็นคุณสมบัติที่ขอให้จัดการกับมันได้อย่างถูกต้องใน Docker
gertvdijk

2
@AlexeyStrakh คุณสามารถลองใช้ "/ usr / bin / sleep 600" จากนั้นทำ "docker exec -it / bin / bash" เพื่อรับเชลล์ แม้ว่าฉันไม่แน่ใจว่าจะใส่พารามิเตอร์ในตัวแปร Path นั้นได้อย่างไร มิฉะนั้นลองและหาคำสั่งอื่นที่จะมีชีวิตอยู่ได้นานพอสำหรับคุณที่จะทำ exec หรือดูคำตอบจาก Dmitriusan
aaa90210

3
นั่นเป็นเพียงคำตอบที่ถูกต้องสำหรับคำถาม: ข้อเสนออื่น ๆ ทั้งหมดใช้คอนเทนเนอร์ "เกือบเหมือนกัน" แต่พวกเขาลืมโวลุ่ม env, UID, ...
Florian Klein

3
ในกรณีของฉัน / usr / bin / sleep ไม่สามารถใช้ได้ ฉันประสบความสำเร็จกับ..."Path":"tail","Args":["-f","/dev/null"]...
nevrome

4
รุ่นใหม่ของนักเทียบท่าได้config.v2.jsonที่คุณจะต้องมีการเปลี่ยนแปลงอย่างใดอย่างหนึ่งหรือEntrypoint Cmd
user60561

20

เพิ่มการตรวจสอบที่ด้านบนสุดของสคริปต์จุดเข้าใช้งานของคุณ

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

หากคุณยังไม่มีสคริปต์จุดเข้าใช้งานให้สร้างสคริปต์ที่รันคำสั่งใดก็ได้ที่คุณต้องการสำหรับคอนเทนเนอร์ของคุณ จากนั้นที่ด้านบนของไฟล์นี้เพิ่มบรรทัดเหล่านี้ไปที่entrypoint.sh:

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

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

docker run -t --entrypoint entrypoint.sh image_name

สิ่งนี้จะทำให้สคริปต์รันหนึ่งครั้งสร้างไฟล์ที่ระบุว่ามันรันอยู่แล้ว (ในระบบไฟล์เสมือนของคอนเทนเนอร์) จากนั้นคุณสามารถรีสตาร์ทคอนเทนเนอร์เพื่อทำการดีบัก:

docker start container_name

เมื่อคุณรีสตาร์ทคอนเทนเนอร์already_ranจะพบไฟล์ทำให้สคริปต์ Entrypoint หยุดทำงานด้วยcat(ซึ่งจะรอตลอดไปสำหรับอินพุตที่จะไม่มา แต่จะทำให้คอนเทนเนอร์มีชีวิตอยู่) จากนั้นคุณสามารถเรียกใช้bashเซสชันการดีบัก:

docker exec -i container_name bash

ในขณะที่คอนเทนเนอร์กำลังทำงานคุณยังสามารถลบalready_ranและเรียกใช้entrypoint.shสคริปต์ด้วยตนเองอีกครั้งเพื่อรันใหม่หากคุณต้องการดีบักวิธีดังกล่าว


3
นอกจากนี้คุณสามารถทำให้จุดเข้าใช้งานทำงาน/bin/shแทนcat- จากนั้นคุณสามารถเริ่มต้นใหม่ได้ตลอดเวลา ทางออกของคุณสั่นคลอน!
Danny Dulai

4

ปัญหาของฉัน:

  • ฉันเริ่มภาชนะด้วย docker run <IMAGE_NAME>
  • แล้วเพิ่มบางไฟล์ลงในคอนเทนเนอร์นี้
  • จากนั้นฉันปิดคอนเทนเนอร์และพยายามเริ่มต้นอีกครั้งโดยใช้คำสั่งเดียวกับข้างบน
  • แต่เมื่อฉันตรวจสอบไฟล์ใหม่พวกเขาหายไป
  • เมื่อฉันวิ่งdocker ps -aฉันเห็นตู้คอนเทนเนอร์สองตู้
  • นั่นหมายความว่าทุกครั้งที่ฉันใช้docker run <IMAGE_NAME>คำสั่งภาพใหม่จะถูกสร้างขึ้น

การแก้ไข: เมื่อต้องการทำงานบนคอนเทนเนอร์เดียวกันกับที่คุณสร้างขึ้นในตอนแรกให้ทำตามขั้นตอนเหล่านี้

  • docker ps เพื่อรับคอนเทนเนอร์ของคอนเทนเนอร์ของคุณ
  • docker container start <CONTAINER_ID> เพื่อเริ่มคอนเทนเนอร์ที่มีอยู่
  • จากนั้นคุณสามารถดำเนินการต่อจากที่ที่คุณทิ้งไว้ เช่นdocker exec -it <CONTAINER_ID> /bin/bash
  • จากนั้นคุณสามารถตัดสินใจที่จะสร้างภาพใหม่จากมัน

สิ่งนี้ไม่ตอบคำถาม OP ต้องการทราบวิธีการรีสตาร์ทคอนเทนเนอร์ แต่มีอาร์กิวเมนต์ที่แตกต่างจากที่ใช้ในdocker run <containerID>
CodeBlooded

2

ฉันตอบ @ Dmitriusan และทำให้เป็นนามแฝง:

alias docker-run-prev-container = 'prev_container_id = "$ (นักเทียบท่า ps -aq | head -n1)" && นักเทียบท่ายอมรับ "$ prev_container_id" "prev_container / $ prev_container_id" && นักเทียบท่าวิ่ง - มัน - ผู้ใช้ปลายทาง - ผู้ใช้ปลายทาง = bash "prev_container / $ prev_container_id'

เพิ่มสิ่งนี้ลงใน~/.bashrcไฟล์นามแฝงของคุณและคุณจะมีdocker-run-prev-containerนามแฝงใหม่ที่ดีซึ่งจะนำคุณไปสู่เชลล์ในคอนเทนเนอร์ก่อนหน้า

ที่เป็นประโยชน์สำหรับการแก้จุดบกพร่องล้มเหลวdocker builds


2

นี่ไม่ใช่สิ่งที่คุณต้องการ แต่คุณสามารถใช้docker exportบนคอนเทนเนอร์ที่หยุดถ้าสิ่งที่คุณต้องการคือการตรวจสอบไฟล์

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

1

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

รับรหัสคอนเทนเนอร์ด้วย docker ps

docker exec -it 665b4a1e17b6 /bin/sh

หากจุดเข้าใช้งานถูกตั้งค่าเป็นสิ่งที่มีปัญหาก็สามารถแทนที่ได้ตามคำแนะนำในคำตอบของ Dmitriusan มันก็ควรจะตั้งข้อสังเกตว่าคุณสามารถแนบไปกับภาชนะใด ๆ docker attachกับการทำงาน วิธีแก้ปัญหาต่าง ๆ มากมาย ฉันไม่เห็นว่าจำเป็นต้องกระทำกับภาพ ดูเหมือนไม่จำเป็น

Docs สำหรับ Docker exec - https://docs.docker.com/engine/reference/commandline/exec/

เอกสารสำหรับนักเทียบท่าแนบ - https://docs.docker.com/engine/reference/commandline/attach/


-12

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

docker run -it <image_name> bash

12
สิ่งนี้ไม่ทำงานเมื่อ op ถามเกี่ยวกับคอนเทนเนอร์ไม่ใช่รูปภาพ
Peter Vrabel

ฉันคิดว่าสิทธิ์ของคุณ แต่ไม่เห็นเหตุผลที่จะทำเช่นนั้น คุณสามารถไพพ์ล็อกเพื่อ stdout และdocker logs <container_id> --followจะให้สิ่งที่คุณต้องการ อีกทางเลือกหนึ่งคือการใช้คำสั่งด้านบนจากนั้นเริ่มบริการการขัดข้องบนอิมเมจนั้นด้วยคำสั่งเดียวกันใน dockerfile และดีบักจากที่นั่น
deadbabykitten

4
คำสั่ง run สร้างคอนเทนเนอร์ใหม่จากอิมเมจ มันไม่เริ่มต้นคอนเทนเนอร์ที่หยุด
Waleed Abdulla

2
อืมมมม .. จุดแข็งของท่าเทียบเรือก็คือทุกภาพสามารถหมุนไปในทิศทางเดียวกันได้หรือไม่? สิ่งนี้ขัดแย้งกับการโต้แย้งของคุณ เขาไม่ต้องการเริ่มภาชนะที่หยุด ภาชนะใด ๆ นั้นเหมือนกันดังนั้นจึงไม่สำคัญว่าจะใช้ภาชนะบรรจุใดเริ่มต้นหรือหยุด เขาแค่พยายามตรวจสอบเนื้อหา วิธีที่ง่ายที่สุดคือการทุบตีและเรียกใช้คำสั่งหรือเอาต์พุตไพพ์ของคำสั่งไปยังบันทึก พวกคุณคิดวิธีแก้ปัญหาที่ซับซ้อนที่สุดสำหรับปัญหาง่ายๆ
deadbabykitten

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