Birden çok hizmeti çalıştırmak için Docker CMD'yi neden birden çok kez kullanamıyorum?


98

Dockerfile'dan centos + ssh adında bir temel imaj oluşturdum. Centos + ssh's Dockerfile'da ssh servisini çalıştırmak için CMD kullanıyorum.

Sonra da rabbitmq adlı başka bir hizmet olan Dockerfile çalıştıran bir imaj oluşturmak istiyorum:

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

Rabbitmq konteynerini başlatmak için , çalıştırın ,

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

ancak ssh hizmeti çalışmıyor, rabbitmq'nin Dockerfile CMD'sini centos'un CMD'sini geçersiz kıldığını algılıyor.

  1. CMD, docker görüntüsü içinde nasıl çalışır?
  2. Birden fazla hizmet çalıştırmak istersem, nasıl yapılır? Süpervizör mü kullanıyorsunuz?

Yanıtlar:


64

CMD, Dockerfile'da yazılı olsa da, gerçekten çalışma zamanı bilgisidir. Tıpkı EXPOSE gibi, ancak örneğin RUN ve ADD'nin aksine. Bununla, onu daha sonra, genişleyen bir Dockerfile'da veya çalıştırma komutunuzda basitçe geçersiz kılabileceğinizi kastediyorum, deneyimlediğiniz şey budur. Her zaman yalnızca bir CMD olabilir.

Birden fazla hizmet çalıştırmak istiyorsanız, gerçekten gözetmen kullanırım. Her hizmet için bir gözetmen yapılandırma dosyası oluşturabilir, bunları bir dizine supervisord -c /etc/supervisorekleyebilir ve tüm hizmetlerinizi yükleyen ve benzer görünen bir gözetmen yapılandırma dosyasını işaret etmek için denetleyiciyi çalıştırabilirsiniz.

[supervisord]
nodaemon=true

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

Daha fazla ayrıntı isterseniz, bu konuyla ilgili bir blog yazdım: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image- miras /


Teşekkürler, süpervizör iyi bir fikir, ancak CMD'nin docker görüntüsü içinde nasıl çalıştığını merak ediyorum
edwardsbean

2
İki soru sordunuz, 2. birden fazla hizmetin çalıştırılmasıyla ilgili. CMD'nin nasıl çalıştığını merak ettiğinizde, lütfen özellikle neyi bilmek istediğinizi detaylandırın. Daha önce çalışma zamanı bilgisi olduğundan ve herhangi bir yeni CMD tarafından üzerine yazıldığından bahsetmiştim.
qkrijger

119

Haklısın, ikinci Dockerfile, ilkinin CMDkomutunun üzerine yazacak . Docker her zaman tek bir komut çalıştırır, fazlasını değil. Yani Dockerfile'ınızın sonunda çalıştırmak için bir komut belirtebilirsiniz . Daha fazla değil.

Ancak her iki komutu da tek satırda çalıştırabilirsiniz:

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

Dockerfile'ınızı biraz daha temiz hale getirmek için yapabilecekleriniz, CMD komutlarınızı fazladan bir dosyaya koyabilirsiniz:

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

Ve bunun gibi bir dosya:

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

1
teşekkürler, süpervizör kullanmanın daha iyi olduğunu düşünüyorum. ama docker neden sadece bir CMD çalıştırıyor? içinde ne oluyor?
edwardsbean

1
İçeride ne olduğunu bilmiyorum. Ama bence sadece böyle tasarlandı. Bir görüntünüz olduğunda ve içinde bir komut çalıştırdığınızda (örneğin CMD ile), bir konteyner başlatır. Kap, komut çalıştığı sürece çalışır. Ve komut biter bitmez, konteyner de durur. Yani her bir konteyner tek bir (çalışan) komutu temsil eder.
Thomas Uhrig

Sanırım bunun nedeni lcx veya başka bir şeyin sınırı
edwardsbean

2
@ Tyguy7 .. çünkü ................?
StartupGuy

1
&&teknik yalnızca etkileşimli olmayan hizmetlerle (arka planda başlayabilen) çalışır, aksi takdirde yalnızca ilki çalışır.
noraj

27

Qkrijger'ın bu konuda nasıl çalışabileceğinizi açıklayan cevabına saygı duyarken, burada neler olup bittiğini öğrenebileceğimiz daha çok şey olduğunu düşünüyorum ...

Aslında " neden " sorunuzu yanıtlamak için ... docker stopKomutun nasıl çalıştığını ve yeniden başlatmaya çalıştığınızda sorunları (dosya bozulması vb.) Önlemek için tüm işlemlerin temiz bir şekilde kapatılması gerektiğini anlamanızın size yardımcı olacağını düşünüyorum .

Sorun: liman işçisi Ya yaptılar 's komutundan başlangıç SSH ve sizin Docker dosyasından RabbitMQ başladı? " Docker stop komutu, konteynırdaki kök sürece (PID 1) bir SIGTERM sinyali göndererek önce çalışan bir konteyneri durdurmaya çalışır. " Docker, SIGTERM'i alacak olan PID 1 olarak hangi süreç izliyor? SSH mi yoksa Tavşan mı? "Unix süreç modeline göre, init süreci - PID 1 - tüm öksüz alt süreçleri miras alır ve bunları biçmelidir. Çoğu Docker konteynerinin bunu doğru bir şekilde yapan bir init süreci yoktur ve sonuç olarak konteynerleri zaman içinde zombi süreçleri. "

Cevap: Docker basitçe o son CMD alır biri olarak lanse alacak kök süreci PID 1 ile ve gelen SIGTERM olsun docker stop.

Önerilen çözüm: phusion / baseimage gibi birden fazla hizmeti çalıştırmak için özel olarak hazırlanmış bir temel görüntü kullanmalısınız (veya oluşturmalısınız)

Dikkat etmek önemlidir olmalıdır tini bu nedenle tam olarak var ve Docker 1.13 ve yukarı olarak, tini resmen Docker birden fazla işlemi çalıştıran söyler Docker bir parçasıdır GEÇERLİ OLDUĞU .. bu yüzden bile birisi için iddialar Docker konusunda daha yetenekli olun ve bunu yapmayı düşündüğünüz için saçma olduğunuzda ısrar ediyor, olmadığınızı bilin. Bunu yapmak için tamamen geçerli durumlar var.

Bunu bildiğim iyi oldu:


3

Bir konteynerde birden fazla hizmet çalıştırmanın resmi docker cevabı .

Bunu bir init sistemi (systemd, sysvinit, upstart), bir script ( CMD ./my_wrapper_script.sh) veya benzeri bir süpervizör ile nasıl yapabileceğinizi açıklar supervisord.

&&Geçici çözüm arkaplan (cinleri) başlar hizmetler için sadece çalışabilir ya da bu etkileşimi olmadan hızlı yürütmek ve hızlı yayınlayacak. Bunu etkileşimli bir hizmetle yapmak (istemi tutan) ve yalnızca ilk hizmet başlayacaktır.


0

CMD'nin neden konteyner başına yalnızca bir hizmet çalıştıracak şekilde tasarlandığını ele almak için, aynı kapta çalışan ikincil sunucular önemsiz / yardımcı değil, "büyük" (örneğin, ön uç uygulamasıyla birlikte paketlenmiş depolama) ise ne olacağını anlayalım. Yeni başlayanlar için, her ikisi de konteyner başına yalnızca bir uygulama (CPU yükü kaynağı) olduğunu varsayan yatay (otomatik) ölçeklendirme ve düğümler arasında yeniden zamanlama gibi birkaç önemli konteynerleştirme özelliğini bozacaktır. Bir de güvenlik açıkları sorunu var - bir konteynerde daha fazla sunucu açığa çıkması, CVE'lerin daha sık yaması anlamına geliyor ...

Öyleyse kabul edelim ki Docker (ve Kubernetes / Openshift) tasarımcılarının iyi uygulamalara doğru bir 'dürtüsü' ve geçici çözümleri yeniden icat etmemeliyiz (SSH gerekli değildir - onu docker exec / kubectl exec / oc rshdeğiştirmek için tasarladık).

  • Daha fazla bilgi

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.