เป็นไปได้ไหมที่จะเริ่มเชลล์เซสชันในคอนเทนเนอร์ที่รันอยู่ (ไม่มี ssh)


341

ฉันคาดหวังอย่างไร้เดียงสาว่าคำสั่งนี้ใช้ bash shell ในคอนเทนเนอร์ที่รันอยู่:

docker run "id of running container" /bin/bash

ดูเหมือนว่าเป็นไปไม่ได้ฉันได้รับข้อผิดพลาด:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

ดังนั้นถ้าฉันต้องการรัน bash shell ใน container ที่ทำงานอยู่ (เช่นเพื่อการวินิจฉัย)

ฉันต้องใช้เซิร์ฟเวอร์ SSH ในนั้นและเข้าสู่ระบบผ่าน ssh ได้อย่างไร


1
docker run CONTAINERมีการวางแผนใน 1.0
kolypto

7
ตั้งแต่นักเทียบท่า 1.3 คุณควรทำตามที่อธิบายไว้ในคำตอบนี้
Thomasleveil

1
justdocker attach container_name
maxbellec

1
ดูเหมือนว่าคำตอบที่สองในปัจจุบันดีกว่าคำตอบที่ได้รับมาก - คุณสามารถพิจารณาคำตอบที่ยอมรับได้ไหม
jsbueno

คำตอบ:


285

แก้ไข: ตอนนี้คุณสามารถใช้docker exec -it "id of running container" bash( doc )

ก่อนหน้านี้คำตอบสำหรับคำถามนี้คือ:

หากคุณต้องจริงๆและคุณอยู่ในสภาพแวดล้อมการดีบักคุณสามารถทำได้: sudo lxc-attach -n <ID> โปรดทราบว่ารหัสต้องเป็นรหัสเต็ม ( docker ps -notrunc)

อย่างไรก็ตามฉันขอแนะนำอย่างยิ่งกับสิ่งนี้

ประกาศ: -notruncเลิกใช้แล้วจะถูกแทนที่โดย--no-truncเร็ว ๆ นี้


1
ทำไมคุณถึงแนะนำกับมัน?
Max L.

7
ฉันแนะนำต่อเนื่องจากเพราะ 1) มันต้องใช้เคอร์เนลล่าสุด 2) คุณกำลังทำสิ่งนอกนักเทียบท่าดังนั้นคุณจะไม่สามารถติดตามได้ (บันทึกแนบและอื่น ๆ ) นอกจากนี้นักเทียบท่าอาจใช้ lxc ในตอนนี้ แต่ไม่มีการรับประกันว่าจะทำเช่นนี้ตลอดไป
creack

1
ลองอัปเดตเป็น 0.7.6 นักเทียบท่ายังคงใช้ lxc อยู่ในขณะนี้และlxc-attachควรใช้งานได้ดี ฉันเพิ่งตรวจสอบสองเท่าและใช้งานได้สำหรับฉัน (โปรดทราบว่ามันจะไม่ทำงานกับเคอร์เนลก่อนหน้า 3.8)
creack

2
ตั้งแต่ 0.9 นักเทียบท่าจะไม่ทำงานกับ LXC อีกต่อไปโดยค่าเริ่มต้น คุณจะต้องเปิดตัวนักเทียบท่า deamon ด้วยdocker -d -e lxc
kevzettler

2
แม็กซ์ลิตรกรณีการใช้งานของคุณสามารถแก้ไขได้ด้วยปริมาณข้อมูล ตัวอย่างที่ไม่ได้ทดสอบ: 1) เรียกใช้คอนเทนเนอร์ที่มีบันทึก nginx ในปริมาณข้อมูล: docker run -v /var/log/nginx -name somename imagename command; 2) docker run -volumes-from somename -i -t busybox /bin/shเรียกใช้ภาชนะเพื่อดูเนื้อหาปริมาณข้อมูลอื่น:
ciastek

615

กับนักเทียบท่า 1.3 docker execมีคำสั่งใหม่ สิ่งนี้ช่วยให้คุณป้อนนักเทียบท่าที่กำลังทำงานอยู่:

docker exec -it "id of running container" bash

2
มันใช้งานได้ดีสำหรับฉัน นอกจากนี้มีประโยชน์มากในการทำงานนักเทียบท่า
oraserrata

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

มีประโยชน์มาก. ขอบคุณ
luongnv89

ใช้docker psเพื่อรับ id ของอินสแตนซ์ที่ใช้งานอยู่
muon

หมายเหตุ: คอนเทนเนอร์อาจไม่มี bash (» exec: "bash": ไม่พบไฟล์เรียกทำงาน«) ใช้docker inspect <image>เพื่อดูว่ามีเปลือกอะไรบ้าง เช่นเรียกใช้docker exec -it <container id> /bin/shแทน
pixelbrackets

14

แค่ทำ

docker attach container_name

ตามที่ระบุไว้ในความคิดเห็นที่จะแยกออกจากภาชนะโดยไม่ต้องหยุดพิมพ์แล้วCtrlpCtrlq


5
ขอบคุณ !! มันช่วยได้ และในบริบทของคำถามจริงฉันต้องการเพิ่มบางสิ่ง หลังจากการแก้จุดบกพร่องของเราโดยใช้ภาชนะ, docker attach container_nameใช้ctrl pและแทนctrl q คำสั่งหยุดภาชนะที่เป็นและเพียงแค่แยกภาชนะที่และช่วยให้มันทำงานexitexitctrlpctrl q
ฟีนิกซ์

10

เนื่องจากสิ่งที่ achanging nsenterในขณะที่วิธีที่แนะนำในการเข้าถึงภาชนะที่ทำงานคือการใช้

คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับที่เก็บ GitHubนี้ แต่โดยทั่วไปคุณสามารถใช้ nsenter เช่นนี้:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

หรือคุณสามารถใช้กระดาษห่อdocker-enter:

docker-enter <container_name_or_ID>

คำอธิบายที่ดีเกี่ยวกับหัวข้อสามารถพบได้ในรายการบล็อกของJérôme Petazzoni: ทำไมคุณไม่จำเป็นต้องเรียกใช้ sshd ในคอนเทนเนอร์นักเทียบท่าของคุณ


น่าเสียดายที่ตัวแปร env ถูกทำให้สับสนโดยใช้วิธีการนี้ (หากคุณต้องการตรวจสอบตัวแปรที่สร้างโดยลิงก์) source /proc/*/environผมขอแนะนำให้ทำ
Tomas Tomecek

8

สิ่งแรกที่คุณไม่สามารถวิ่งได้

docker run "existing container" command

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

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

ฉันรันคำสั่งผ่านหัวหน้างานในโหมด DEAMON

จากนั้นฉันก็เรียกใช้สิ่งที่ฉันเรียกdocker_loop.sh ว่าเนื้อหามันค่อนข้างมาก:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

มันคืออะไรที่ช่วยให้คุณ "แนบ" กับภาชนะและนำเสนอด้วยsupervisorctlอินเตอร์เฟซเพื่อหยุด / เริ่ม / เริ่มต้นใหม่และตรวจสอบบันทึก หากนั่นไม่เพียงพอคุณสามารถCtrl+Dและคุณจะวางลงในเชลล์ที่จะช่วยให้คุณมองไปรอบ ๆ ราวกับว่ามันเป็นระบบปกติ

โปรดทำตามบัญชีที่ระบบนี้ไม่ปลอดภัยเท่ากับมีคอนเทนเนอร์ที่ไม่มีเชลล์ดังนั้นทำตามขั้นตอนที่จำเป็นทั้งหมดเพื่อรักษาความปลอดภัยคอนเทนเนอร์ของคุณ


5

จับตาดูคำขอดึงนี้: https://github.com/docker/docker/pull/7409

ซึ่งใช้docker exec <container_id> <command>ยูทิลิตี้ที่กำลังจะมา เมื่อสิ่งนี้พร้อมใช้งานเป็นไปได้เช่นเริ่มและหยุดบริการ ssh ภายในคอนเทนเนอร์ที่ใช้งานอยู่

นอกจากนี้ยังมีnsinitการทำเช่นนี้: "nsinit ให้วิธีที่สะดวกในการเข้าถึงเชลล์ภายในเนมสเปซของคอนเทนเนอร์ที่ใช้งาน"แต่ดูเหมือนยากที่จะเรียกใช้ https://gist.github.com/ubergarm/ed42ebbea293350c30a6


docker execลงจอดใน Docker 1.3 ดังนั้นตอนนี้จึงเป็นไปได้ที่จะสร้างและเข้าร่วมเซสชั่นเชลล์ใหม่ในคอนเทนเนอร์ที่ทำงาน
foz


1

จริงๆแล้วมีวิธีที่จะมีเปลือกในภาชนะ

สมมติว่าคุณ/root/run.shเปิดตัวกระบวนการผู้จัดการกระบวนการ (หัวหน้างาน) หรืออะไรก็ตาม

สร้าง/root/runme.shด้วยเทคนิค gnu-screen บางอย่าง:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

ตอนนี้คุณมีดีมอนของคุณในแท็บ 0 และเชลล์แบบโต้ตอบในแท็บ 1 docker attachได้ตลอดเวลาเพื่อดูว่าเกิดอะไรขึ้นภายในคอนเทนเนอร์

คำแนะนำอีกอย่างคือการสร้างอิมเมจ "กลุ่มการพัฒนา" ด้านบนของอิมเมจการผลิตด้วยเครื่องมือที่จำเป็นทั้งหมดรวมถึงเคล็ดลับหน้าจอนี้


1

นี่คือทางออกของฉัน

ส่วนหนึ่งของ DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

ส่วนหนึ่งของ "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

หลังจากสร้างภาพคุณมีสองตัวเลือกโดยใช้ exec และแนบ:

  1. ด้วย exec (ซึ่งฉันใช้) รัน:

นักวิ่ง - ชื่อ $ CONTAINER_NAME - ไม่ $ IMAGE_NAME

แล้วก็

นักเทียบท่า exec -it $ CONTAINER_NAME / bin / bash

และการใช้งาน

CTRL + D เพื่อถอด

  1. ด้วยไฟล์แนบให้เรียกใช้:

นักวิ่ง - ชื่อ $ CONTAINER_NAME - แก้ไข $ IMAGE_NAME

แล้วก็

นักเทียบท่าแนบ $ CONTAINER_NAME

และการใช้งาน

CTRL + P และ CTRL + Q เพื่อแยกออก

ความแตกต่างระหว่างตัวเลือกอยู่ในพารามิเตอร์-i


1

มีสองวิธี

พร้อมแนบ

$ sudo docker attach 665b4a1e17b6 #by ID

ด้วยผู้บริหาร

$ sudo docker exec - -t 665b4a1e17b6 #by ID

0

หากเป้าหมายคือการตรวจสอบบันทึกของแอปพลิเคชันโพสต์นี้จะแสดงการเริ่มต้นขึ้นคราวและปรับแต่งบันทึกเป็นส่วนหนึ่งของ CMD บันทึก Tomcat มีอยู่ในโฮสต์โดยใช้ 'docker logs containerid'

http://blog.trifork.com/2013/08/15/using-docker-to-efficiently-create-multiple-tomcat-instances/


0

เป็นชื่อกำหนดที่มีประโยชน์เมื่อเรียกใช้คอนเทนเนอร์ คุณไม่จำเป็นต้องดู container_id

docker run --name container_name yourimage docker exec -it container_name bash


0

ก่อนอื่นรับรหัสคอนเทนเนอร์ของคอนเทนเนอร์ที่ต้องการโดย

docker ps

คุณจะได้รับสิ่งนี้:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

ตอนนี้คัดลอก id คอนเทนเนอร์นี้และเรียกใช้คำสั่งต่อไปนี้:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh


-2

บางทีคุณอาจทำให้เข้าใจผิดคิดว่าในแง่ของ VMs เมื่อพัฒนาตู้คอนเทนเนอร์ คำแนะนำของฉัน: พยายามที่จะไม่

ภาชนะบรรจุเป็นเหมือนกระบวนการอื่นใด แน่นอนคุณอาจต้องการ "แนบ" เพื่อแก้ไขจุดบกพร่อง (คิด / proc // env หรือ strace -p) แต่นั่นเป็นกรณีพิเศษมาก

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

สำหรับวัตถุประสงค์ในการดีบั๊กคุณอาจต้องการเริ่มเชลล์จากนั้นโค้ดของคุณจากนั้นกด CTRL-p + CTRL-q เพื่อให้เชลล์ยังคงอยู่ วิธีนี้คุณสามารถติดตั้งใหม่โดยใช้:

docker attach <container_id>

หากคุณต้องการดีบักคอนเทนเนอร์เนื่องจากทำสิ่งที่คุณไม่คาดคิดให้ลองแก้ปัญหา: /server/596994/how-can-i-debug-a-docker-container -การเริ่มต้น


นี่เป็นสิ่งที่ผิดอย่างสิ้นเชิง ความสามารถในการไตร่ตรอง LXC เนมสเปซที่แอปพลิเคชันของคุณกำลังทำงานอยู่นั้นไม่ใช่ "กรณีที่พิเศษมาก" มันเป็นกิจกรรมทั่วไป / รายวันสำหรับนักพัฒนา
sleepycal

@sleepycal "นักพัฒนาใด ๆ " ฟังดูลำเอียงเล็กน้อย ในกรณีใด ๆ ฉันใช้วิปัสสนาของกระบวนการดังนั้นสิ่งเดียวกันกับคอนเทนเนอร์ นั่นเป็นแนวคิดที่อยู่เบื้องหลังการแก้ไขข้อบกพร่อง คุณแนบดีบักเกอร์กับกระบวนการ (ซึ่งอาจมี cli) การคิดว่าคุณ "เข้า" เข้าสู่ระบบในภาชนะเสียงยังคงทำให้เข้าใจผิดฉัน
estani

-4

ไม่ได้นี่เป็นไปไม่ได้ ใช้สิ่งที่ต้องการsupervisordรับเซิร์ฟเวอร์ ssh หากจำเป็น แม้ว่าฉันจะถามความต้องการอย่างแน่นอน

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