เหตุใดฉันจึงใช้ Docker CMD หลายครั้งเพื่อเรียกใช้บริการหลาย ๆ บริการไม่ได้


101

ฉันได้สร้างอิมเมจพื้นฐานจาก Dockerfile ชื่อ centos + ssh ใน Dockerfile ของ centos + ssh ฉันใช้ CMD เพื่อเรียกใช้บริการ ssh

จากนั้นฉันต้องการสร้างอิมเมจเพื่อเรียกใช้บริการอื่นที่ชื่อ rabbitmq Dockerfile:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start

ในการเริ่มต้น rabbitmq container, ให้รัน:

docker run -d -p 222:22 -p 4149:4149 rabbitmq

แต่บริการ ssh ใช้ไม่ได้มันรู้สึกว่า Dockerfile CMD ของ rabbitmq แทนที่ CMD ของ centos

  1. CMD ทำงานอย่างไรในภาพนักเทียบท่า
  2. หากต้องการเรียกใช้บริการหลายรายการต้องทำอย่างไร? ใช้หัวหน้างาน?

คำตอบ:


65

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

หากคุณต้องการเรียกใช้บริการหลายอย่างฉันจะใช้หัวหน้างาน คุณสามารถสร้างไฟล์คอนฟิกูเรชันของผู้ดูแลสำหรับแต่ละบริการเพิ่มสิ่งเหล่านี้ในไดเร็กทอรีและเรียกใช้หัวหน้างานโดยsupervisord -c /etc/supervisorชี้ไปที่ไฟล์คอนฟิกูเรชันของผู้ดูแลซึ่งโหลดบริการทั้งหมดของคุณและดูเหมือนว่า

[supervisord]
nodaemon=true

[include]
files = /etc/supervisor/conf.d/*.conf

หากคุณต้องการรายละเอียดเพิ่มเติมฉันเขียนบล็อกเกี่ยวกับเรื่องนี้ที่นี่: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image- มรดก /


ขอบคุณหัวหน้างานเป็นความคิดที่ดี แต่ฉันสงสัยว่า CMD ทำงานอย่างไรในภาพนักเทียบท่า
edwardsbean

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

119

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

แต่คุณสามารถดำเนินการทั้งสองคำสั่งในบรรทัดเดียว:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start

สิ่งที่คุณสามารถทำได้เพื่อทำให้ Dockerfile ของคุณสะอาดขึ้นเล็กน้อยคุณสามารถใส่คำสั่ง CMD ของคุณไปยังไฟล์พิเศษ

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh

และไฟล์เช่นนี้:

service sshd start &
/opt/mq/sbin/rabbitmq-server start

1
ขอบคุณฉันคิดว่าการใช้หัวหน้างานดีกว่า แต่ทำไมนักเทียบท่าจึงเรียกใช้ CMD เพียงตัวเดียวเกิดอะไรขึ้นข้างใน?
edwardsbean

1
ไม่รู้ว่าข้างในเกิดอะไรขึ้น แต่ฉันคิดว่ามันออกแบบมาอย่างนั้น เมื่อคุณมีอิมเมจและรันคำสั่งในนั้น (เช่นด้วย CMD) มันจะเริ่มคอนเทนเนอร์ คอนเทนเนอร์ทำงานตราบเท่าที่คำสั่งรัน และทันทีที่คำสั่งเสร็จสิ้นคอนเทนเนอร์ก็จะหยุดลงด้วย ดังนั้นแต่ละคอนเทนเนอร์จึงแทนคำสั่งเดียว (กำลังทำงาน)
Thomas Uhrig

ฉันคิดว่าอาจเป็นเพราะ lcx หรือขีด จำกัด ของอะไรบางอย่าง
edwardsbean

2
@ Tyguy7 .. เพราะ ................ ?
StartupGuy

1
&&เทคนิคจะใช้ได้เฉพาะกับบริการที่ไม่โต้ตอบเท่านั้น (ซึ่งสามารถเริ่มทำงานในพื้นหลังได้) มิฉะนั้นจะมีเพียงบริการแรกเท่านั้นที่ทำงาน
noraj

27

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

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

ปัญหา: เกิดอะไรขึ้นถ้านักเทียบท่าได้ SSH เริ่มต้นจากคำสั่งของมันและเริ่ม RabbitMQ จากแฟ้มเทียบท่าของคุณหรือไม่ " คำสั่งหยุดนักเทียบท่าจะพยายามหยุดคอนเทนเนอร์ที่กำลังทำงานก่อนโดยส่งสัญญาณ SIGTERM ไปยังกระบวนการรูท (PID 1) ในคอนเทนเนอร์ " กระบวนการใดที่นักเทียบท่าติดตามเป็น PID 1 ที่จะได้รับ SIGTERM จะ SSH หรือ Rabbit ?? "ตามแบบจำลองกระบวนการ Unix กระบวนการเริ่มต้น - PID 1 - สืบทอดกระบวนการลูกที่ถูกทอดทิ้งทั้งหมดและต้องเก็บเกี่ยวพวกเขาคอนเทนเนอร์ Docker ส่วนใหญ่ไม่มีกระบวนการเริ่มต้นที่ทำสิ่งนี้ได้อย่างถูกต้องและส่งผลให้คอนเทนเนอร์ของพวกเขาเต็มไปด้วย ซอมบี้ประมวลผลเมื่อเวลาผ่านไป "

คำตอบ: เทียบท่าใช้เวลาเพียงแค่ว่า CMD ที่ผ่านมาเป็นอย่างใดอย่างหนึ่งที่จะได้รับการเปิดตัวเป็นกระบวนการรากกับ PID 1 และได้รับ SIGTERM docker stopจาก

วิธีแก้ปัญหาที่แนะนำ: คุณควรใช้ (หรือสร้าง) อิมเมจพื้นฐานที่สร้างขึ้นโดยเฉพาะสำหรับการเรียกใช้บริการมากกว่าหนึ่งบริการเช่นฟิวชั่น / เบสอิมเมจ

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

ดีแล้วที่รู้:


3

คำตอบนักเทียบท่าอย่างเป็นทางการเพื่อเรียกใช้บริการหลายในภาชนะ

มันอธิบายวิธีการที่คุณสามารถทำมันได้ด้วยระบบ init (systemd, sysvinit พุ่งพรวด) สคริปต์ ( CMD ./my_wrapper_script.sh) supervisordหรือผู้บังคับบัญชาเช่น

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


0

เพื่อระบุสาเหตุที่ CMD ออกแบบมาให้เรียกใช้บริการเดียวต่อคอนเทนเนอร์เรามาดูกันว่าจะเกิดอะไรขึ้นหากเซิร์ฟเวอร์รองที่ทำงานในคอนเทนเนอร์เดียวกันไม่ใช่เรื่องเล็กน้อย / เสริม แต่เป็น "หลัก" (เช่นพื้นที่เก็บข้อมูลที่มาพร้อมกับแอปส่วนหน้า) สำหรับผู้เริ่มต้นจะแบ่งคุณสมบัติการจัดคอนเทนเนอร์ที่สำคัญหลายอย่างเช่นการปรับขนาดแนวนอน (อัตโนมัติ) และการปรับขนาดระหว่างโหนดซึ่งทั้งสองถือว่ามีเพียงแอปพลิเคชันเดียว (แหล่งที่มาของการโหลด CPU) ต่อคอนเทนเนอร์ จากนั้นก็มีปัญหาเรื่องช่องโหว่ - เซิร์ฟเวอร์จำนวนมากที่เปิดเผยในคอนเทนเนอร์หมายถึงการแก้ไข CVE บ่อยขึ้น ...

ดังนั้นยอมรับว่าเป็นการ 'สะกิด' จากนักออกแบบ Docker (และ Kubernetes / Openshift) ต่อแนวทางปฏิบัติที่ดีและเราไม่ควรคิดค้นวิธีแก้ปัญหาใหม่ (ไม่จำเป็นต้องใช้ SSH - เราได้docker exec / kubectl exec / oc rshออกแบบมาเพื่อแทนที่)

  • ข้อมูลเพิ่มเติม

/devops/447/why-it-is-recommended-to-run-only-one-process-in-a-container

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