คอนเทนเนอร์นักเทียบท่าจะหยุดโดยอัตโนมัติหลังจาก“ นักเทียบท่าเรียกใช้ -d”


333

ตามบทช่วยสอนที่ฉันอ่านมาการใช้ " docker run -d" จะเริ่มต้นคอนเทนเนอร์จากอิมเมจและคอนเทนเนอร์จะทำงานในพื้นหลัง นี่คือลักษณะที่ปรากฏเราสามารถเห็นว่าเรามี ID คอนเทนเนอร์แล้ว

root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

แต่ถ้าฉันวิ่ง " docker ps" ไม่มีอะไรถูกส่งคืน

ดังนั้นฉันจึงลอง " docker ps -a" ฉันเห็นคอนเทนเนอร์ออกแล้ว:

root@docker:/home/root# docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz

ฉันทำอะไรผิดหรือเปล่า? ฉันจะแก้ไขปัญหานี้ได้อย่างไร


1
"นักเทียบท่าเรียกใช้ hello-world" <== ทำงานได้อย่างสมบูรณ์แบบ แต่ถ้าฉันเรียกใช้ "นักเทียบท่าเรียกใช้ -d hello-world" ฉันยังไม่สามารถรับคอนเทนเนอร์ที่ใช้งานได้
J John

5
ฉันมีปัญหาที่คล้ายกัน แต่ฉันได้ทำงานโดยใช้docker run -it -d <image> /bin/bashนี้เริ่มเปลือกทุบตีโต้ตอบและไม่ปิดภาชนะเพราะกระบวนการเปลือกใช้งานอยู่
Rtsne42

คำตอบ:


495

CentOS dockerfilebashมีคำสั่งเริ่มต้น

นั่นหมายความว่าเมื่อทำงานในพื้นหลัง ( -d) เชลล์จะออกจากทันที

อัปเดต 2017

รุ่นอื่น ๆ ที่ผ่านมาของนักเทียบท่าอนุมัติการเรียกใช้ภาชนะทั้งในโหมดแฝด และในโหมดเบื้องหน้า ( -t, -iหรือ-it)

ในกรณีดังกล่าวคุณไม่จำเป็นต้องมีคำสั่งเพิ่มเติมและเพียงพอ:

docker run -t -d centos

ทุบตีจะรอในพื้นหลัง
ที่ได้รับการรายงานครั้งแรกในKalyani-Chaudhari 's คำตอบและรายละเอียดในเสื้อถั่ว ' s คำตอบ

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

โปรดทราบว่าสำหรับอัลไพน์ , Marinosรายงานในการแสดงความคิดเห็น :

docker run -t -d alpine/gitไม่ทำให้กระบวนการดีขึ้น
ต้องทำ:docker run --entrypoint "/bin/sh" -it alpine/git


คำตอบเดิม (2015)

ตามที่กล่าวไว้ในบทความนี้ :

แทนการทำงานด้วยdocker run -i -t image your-commandการใช้-dขอแนะนำเพราะคุณสามารถเรียกใช้ภาชนะของคุณมีเพียงหนึ่งคำสั่งและคุณไม่จำเป็นต้องถอดขั้วของภาชนะโดยการกดปุ่มCtrl+ +PQ

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

ปัญหาคือแอพพลิเคชั่นบางตัวไม่ทำงานในเบื้องหน้า เราจะทำให้ง่ายขึ้นได้อย่างไร

ในสถานการณ์นี้คุณสามารถเพิ่มtail -f /dev/nullคำสั่งของคุณ
ด้วยการทำเช่นนี้แม้ว่าคำสั่งหลักของคุณจะทำงานเป็นแบ็คกราวน์คอนเทนเนอร์ของคุณจะไม่หยุดทำงานเนื่องจาก tail จะทำงานต่อเนื่องในเบื้องหน้า

ดังนั้นสิ่งนี้จะได้ผล:

docker run -d centos tail -f /dev/null

A docker psจะแสดงคอนเทนเนอร์ centos ที่ยังคงทำงานอยู่

จากตรงนั้นคุณสามารถแนบหรือแยกออกจากมัน (หรือdocker execคำสั่งบางอย่าง)


ขออภัยอีกหนึ่งคำถามฉันมีสคริปต์ที่ต้องเรียกใช้เมื่อเริ่มต้นดูเหมือน /etc/rc.d/rc.local ไม่ทำงานอีกต่อไป (ความคิดของฉันยังคงรักษานักเทียบท่าเช่น OS) ฉันคิดว่าไฟล์นักเทียบท่าเป็นตัวเลือกที่ดีกว่าในนี้ กรณี?
J John

5
@GuruprasadGV ที่คาดไว้ docker exec -it <yourContainer> bashแทนการใช้นักเทียบท่าแนบใช้
VonC

3
สิ่งนี้ยังใช้งานได้หากคุณเพิ่มคำสั่ง tail ที่ท้ายไฟล์ entrypoint
yara

2
ฉันใช้ sshd เป็นคำสั่งสุดท้ายของฉัน จากนั้นคุณสามารถ ssh บนคอนเทนเนอร์ของคุณเช่นเดียวกับที่คุณทำบน VM (เมื่อคุณตั้งค่า. ssh / authorized_keys ฯลฯ ) ... คุณยังสามารถกำหนดค่าคอนเทนเนอร์โดยใช้ ansible ได้
andrew pate

1
ฉันลงเอยด้วยการทำเช่นนี้เพื่อรันคำสั่งของฉันพร้อมกับการแก้ไขที่เก่ากว่าที่ระบุไว้ด้านบน: นักเทียบท่าเรียกใช้ image_name / bin / bash -c "my / command && tail -f / dev / null"
Geordie

58

ตามคำตอบนี้การเพิ่มการ-tตั้งค่าสถานะจะป้องกันไม่ให้ออกจากคอนเทนเนอร์เมื่อทำงานในพื้นหลัง จากนั้นคุณสามารถใช้docker exec -i -t <image> /bin/bashเพื่อเข้าสู่ shell prompt

docker run -t -d <image> <command>

ดูเหมือนว่าตัวเลือก -t นั้นไม่ได้รับการบันทึกไว้อย่างดีแต่ความช่วยเหลือบอกว่ามัน "จัดสรรหลอก -TTY"


10
ดี ดูเหมือนว่าtail -f /dev/null
แฮ็ก

ขอบคุณ! ในโอกาสที่เพรียวบางนี้จะช่วยให้ใครบางคนมันไม่ได้ทำงานได้ดีใน Emacs Eshell
Peter Becich

2
docker run -t -d --name mysql -p 3306:3306 mysql- ไม่ทำงานสำหรับฉัน (ubuntu 14.04.5): STATUS = Exited (1) 4 วินาทีที่ผ่านมา
Putnik

ฉันพบว่าคุณไม่ต้องการ <command> ที่นี่ยกเว้นคุณต้องการ น่าแปลกที่มันยังทำงานแทน -t ด้วย -i (แบบโต้ตอบ) เอกสารที่กล่าวถึงการใช้ -t และ -i ที่รวมกันจะทำตัวเหมือนเชลล์
jersey bean

43

พื้นหลัง

คอนเทนเนอร์ Docker เรียกใช้กระบวนการ ("คำสั่ง" หรือ "จุดเข้าใช้งาน") ที่ช่วยให้กระบวนการยังมีชีวิตอยู่ คอนเทนเนอร์จะยังคงทำงานต่อไปตราบใดที่คำสั่งยังคงทำงานต่อไป

ในกรณีของคุณคำสั่ง ( /bin/bashตามค่าเริ่มต้นเปิดcentos:latest) จะออกจากทันที (ตามที่ bash ทำเมื่อไม่ได้เชื่อมต่อกับเทอร์มินัลและไม่มีอะไรทำงาน)

โดยปกติเมื่อคุณเรียกใช้คอนเทนเนอร์ในโหมด daemon (พร้อม-d) คอนเทนเนอร์จะใช้กระบวนการ daemon บางประเภท (เช่นhttpd) ในกรณีนี้ตราบใดที่ httpd daemon กำลังทำงานคอนเทนเนอร์จะยังคงอยู่

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

(คุณหมายถึงการได้รับพร้อมท์ทุบตีภายในคอนเทนเนอร์หรือไม่นั่นง่าย! docker run -it centos:latest)

สารละลาย

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

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

ทางเลือกทางแก้ไข

ตามที่ระบุโดย cjsimon -tตัวเลือกจะจัดสรร "pseudo-tty" เทคนิคนี้ใช้เพื่อดำเนินการต่อไปเรื่อย ๆ เนื่องจากมันคิดว่ามันเชื่อมต่อกับ TTY เชิงโต้ตอบ (แม้ว่าคุณจะไม่มีทางโต้ตอบกับ TTY นั้นถ้าคุณไม่ผ่าน-i) อย่างไรก็ตามสิ่งนี้ควรทำเคล็ดลับเกินไป:

$ docker run -t -d centos:latest

ไม่แน่ใจ 100% ว่า-tจะสร้างการโต้ตอบแปลก ๆ อื่น ๆ หรือไม่ อาจแสดงความคิดเห็นด้านล่างถ้ามัน


หมายเหตุว่านี้ไม่ได้ทำงานบนเทือกเขาแอลป์เป็นนอนหลับ BusyBox infinityไม่ยอมรับ
John Kugelman

สิ่งนี้ช่วยฉันแก้ไขปัญหาภาพอเมซอน - ลินุกซ์ขอบคุณ
ผู้มีอิทธิพล

18

สวัสดีปัญหานี้เป็นเพราะภาชนะนักเทียบท่าออกจากถ้าไม่มีแอปพลิเคชันที่ทำงานอยู่ในภาชนะ

-d 

ตัวเลือกเป็นเพียงการเรียกใช้คอนเทนเนอร์ในโหมด deamon

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

Eg: docker run -d centos sh /yourlocation/start.sh

start.sh นี้ควรชี้ไปที่แอปพลิเคชันที่ไม่มีที่สิ้นสุด

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

ทั้งหมดที่ดีที่สุด


12

คุณสามารถบรรลุสิ่งที่คุณต้องการด้วย:

docker run -t -d <image-name>

หรือ

docker run -i -d <image-name>

หรือ

docker run -it -d <image-name>

พารามิเตอร์คำสั่งที่แนะนำโดยคำตอบอื่น ๆ (เช่น tail -f / dev / null) เป็นทางเลือกที่สมบูรณ์และไม่จำเป็นต้องให้คอนเทนเนอร์ของคุณทำงานในพื้นหลัง

นอกจากนี้โปรดทราบว่าเอกสารประกอบ Docker แนะนำว่าการรวมตัวเลือก -i และ -t จะทำให้มันทำงานเหมือนเชลล์

ดู:

https://docs.docker.com/engine/reference/run/#foreground


9

ฉันมีข้อมูลโค้ดนี้วิ่งจากENTRYPOINTในไฟล์นักเทียบท่าของฉัน:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

เรียกใช้ภาพนักเทียบท่าที่สร้างขึ้นเป็น:

docker run -td <image name>

ล็อกอินเข้าสู่คอนเทนเนอร์เชลล์:

docker exec -it <container id> /bin/bash

นี่เป็นวิธีแก้ปัญหาที่คุณสร้างวงวนไม่สิ้นสุดหรือไม่? : D
Muhammad SaLman

8

ดำเนินการคำสั่งดังต่อไปนี้:

docker run -t -d <image-name>

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

docker run -t -d -p <port-no> <image-name>

ตรวจสอบคอนเทนเนอร์ที่ใช้งานโดยใช้คำสั่งต่อไปนี้:

docker ps

ฉันชอบคำตอบนี้ดีที่สุดเพราะคำตอบยอดนิยมแนะนำว่าคุณต้องการคำสั่ง (เช่น tail -f / dev / null) คำสั่งเป็นทางเลือกที่สมบูรณ์ กุญแจสำคัญในที่นี้คือการใช้ -t ฉันยังพบว่า -i ทำงานแทน -t หรือคุณสามารถใช้ทั้งสองรวมกันได้ (ตามเอกสารแนะนำว่ามันจะทำงานเป็นเชลล์)
jersey bean

มีข้อดีของการใช้-t -dvs -i -d? ทั้งสองจะทำให้คอนเทนเนอร์ทำงาน
wisbucky

5

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

ดังนั้นหากสคริปต์รายการนักเทียบท่าของคุณเป็นกระบวนการพื้นหลังดังต่อไปนี้:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

เครื่องหมาย '&' ทำให้ที่เก็บหยุดและออกหากไม่มีกระบวนการพื้นหน้าอื่น ๆ ที่ถูกทริกเกอร์ในภายหลัง ดังนั้นการแก้ปัญหาก็แค่ลบเครื่องหมาย '&' หรือมี CMD ส่วนหน้าอื่นทำงานอยู่หลังจากนั้นเช่น

tail -f server.log

อาจต้องการtouchไฟล์นั้นก่อนในกรณีที่คุณไม่พบไฟล์บันทึก
Samuel

โดยปกติแล้วไฟล์บันทึกที่ฉันได้รับคือล็อกเซิร์ฟเวอร์ปัจจุบันหรือเอาต์พุตการเปลี่ยนเส้นทางซึ่งควรมีหลังจากเริ่มกระบวนการแล้ว
Peiming Hu

4

ออกจากหางภาชนะถ้าภายในงานจะทำดังนั้นหากคุณต้องการที่จะให้มันมีชีวิตอยู่ถึงแม้ว่ามันจะไม่ได้มีงานใด ๆ docker run -di imageหรือมีอยู่แล้วเสร็จพวกเขาที่คุณสามารถทำได้ หลังจากที่คุณทำdocker container lsคุณจะเห็นมันทำงาน


3

อาจเป็นเพียงฉัน แต่บน CentOS 7.3.1611 และ Docker 1.12.6 แต่ฉันต้องใช้คำตอบที่โพสต์โดย @VonC & @Christopher Simon เพื่อให้การทำงานนี้น่าเชื่อถือ ไม่มีอะไรที่ฉันทำก่อนหน้านี้จะหยุดไม่ให้มีการออกจากคอนเทนเนอร์หลังจากเรียกใช้ CMD ได้สำเร็จ ฉันเริ่ม oracle-xe-11Gr2 และ sshd

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

จากนั้นเพิ่ม -d -t และ -i เพื่อเรียกใช้

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

ในที่สุดหลังจากชั่วโมงของการทุบตีหัวของฉันกับผนัง

ssh -v root@127.0.0.1 -p 5022
...
root@127.0.0.1's password: 
debug1: Authentication succeeded (password).

ไม่ว่าด้วยเหตุผลใดข้างต้นจะจบการทำงานหลังจากเรียกใช้งาน CMD หาก tail -f ถูกลบออกหรือไม่ใช้ตัวเลือก -t -d -i ใด ๆ



1

ฉันมีปัญหาเดียวกันเพียงแค่เปิดเทอร์มินัลอื่นที่มีการทุบตีบนมันทำงานได้สำหรับฉัน:

สร้างคอนเทนเนอร์:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

เริ่มภาชนะ:

docker start 52bbc9b30557

เริ่มทุบตีเพื่อให้ภาชนะทำงาน:

docker exec -it 52bbc9b30557 bash

เริ่มกระบวนการที่คุณต้องการ:

docker exec -it 52bbc9b30557 /path_to_cool_your_app

1

หากคุณใช้ CMD ที่ส่วนท้ายของ Dockerfile ของคุณสิ่งที่คุณสามารถทำได้คือการเพิ่มรหัสในตอนท้าย วิธีนี้จะใช้งานได้ถ้านักเทียบท่าของคุณสร้างบน Ubuntu หรือระบบปฏิบัติการใด ๆ ที่สามารถใช้ทุบตีได้

&& /bin/bash

จุดสิ้นสุดของ Dockerfile ของคุณจะมีลักษณะดังนี้

...

CMD ls && ... && /bin/bash

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


1

การเรียกใช้นักเทียบท่าด้วยโหมดโต้ตอบอาจช่วยแก้ปัญหาได้

นี่คือตัวอย่างสำหรับการเรียกใช้ภาพที่มีและไม่มีโหมดการโต้ตอบ

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo นักเทียบท่าวิ่ง -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18a18

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

รหัสภาพภาชนะบรรจุคำสั่งสร้างสถานะพอร์ตชื่อ

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo นักเทียบท่าวิ่ง -d -t -i test_again1.0 ทุบตี c3d6a9529fd70c5b2dc2d7e90fe662d19856dad8549e9c812fb2b7ce2105d7ff5

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

รหัส ID ภาพคำสั่งสร้างสถานะพอร์ตชื่อ c3d6a9529fd7 test_again1.0 "ทุบตี" 2 วินาทีที่ผ่านมาขึ้น 1 วินาที Awesome_haibt


0

ถ้าคุณต้องการใช้งานบนคอนเทนเนอร์คุณต้องรันมันในเบื้องหน้าเพื่อให้มันมีชีวิตอยู่


-1

คำสั่งอาร์กิวเมนต์มีความสำคัญ

คำตอบของ Jersey Beans (ทั้ง 3 ตัวอย่าง) เหมาะกับฉัน หลังจากการทดลองใช้และข้อผิดพลาดค่อนข้างน้อยฉันก็รู้ว่าลำดับของข้อโต้แย้งนั้นสำคัญ

ให้คอนเทนเนอร์ทำงานในพื้นหลัง: docker run -t -d <image-name>

ช่วยให้คอนเทนเนอร์ทำงานในเบื้องหน้า: docker run <image-name> -t -d

เห็นได้ชัดว่าฉันมาจากพื้นหลัง Powershell

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