Docker CMD direktifinde çoklu komutlar


39

Dockerfile içindeki CMD yönergesiyle çalışma zamanında iki komutu yürütmeye çalıştığımda ne olduğunu anlamıyorum. Bunun işe yarayacağını varsaydım:

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

Ama işe yaramıyor. Konteyner başlatılmadı. Bu yüzden böyle yapmak zorunda kaldım:

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

Anlamadım Neden? Neden ilk satır doğru yol değil? Biri bana bu "CMD kabuk formatı vs JSON formatı, vb" şeylerini açıklayabilir mi. Basit bir deyişle.

Sadece not etmek - aynı beklendiği gibi , içinde command:direktif ile oldu docker-compose.yml.

Yanıtlar:


33

Farkın yapması gerekebileceğine inanıyorum, ikinci komut kabuk işlemeyi gerçekleştirirken ilk komut yapmıyor. Resmi belgelere göre , execve shellkomut vardır, ilk komutunuz bir yürütme biçimidir ve ikincisi de örneğin çevre değişkenlerini genişletmez. Bu nedenle, exec formunu kullanarak komutun kabuk işlemeye bağımlılığı nedeniyle başarısız olabileceği olasıdır. Bunu çalıştırarak kontrol edebilirsinizdocker logs CONTAINERID

İkinci komutunuz, kabuk formuna eşittir -

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

Belgelerden alıntılar -

Not: Kabuk formundan farklı olarak, exec formu bir komut kabuğu çağırmaz. Bu, normal kabuk işlemenin gerçekleşmediği anlamına gelir. Örneğin, CMD [ "echo", "$HOME" ]üzerinde değişken değiştirme yapılmayacaktır $HOME. Eğer kabuk işlemeyi istiyorsanız ya kabuk formunu kullanın veya örneğin doğrudan bir kabuk yürütün: CMD [ "sh", "-c", "echo", "$HOME" ].


Muhtemelen komut, ortam değişkenleri nedeniyle başarısız oldu. execTercih edilen form olduğu için hala bu formu kullanmalı mıyım ? Neden tercih edilir? Yoksa daha basit shellform kullanmalı mıyım?
Vladan

Başarısız oldu, çünkü bir komutu diğerinden sonra çalıştırmak bir kabuk fonksiyonudur. Çevre değişkenleri kırmızı bir ringa balığıdır.
Bryan,

Docker'da birden fazla servis kullanıyorsanız, süpervizör gibi bir işlem yöneticisi kullanmanızı öneririm. Bu şekilde, yalnızca CMD bölümünün altında bir süpervizör başlatıyorsunuz ve hizmetlerin başlatılmasıyla ilgilenecek. Ayrıntıları buradan kontrol edebilirsiniz - docs.docker.com/articles/using_supervisord
Daniel t.

Bu sadece okuduğum tam bir makale :) Teşekkürler.
Vladan

Neden yapman gerektiğini hala anlamıyorum CMD [ "sh", "-c", "echo", "$HOME"]. Neden olmasın CMD ["sh", "-c", "echo $HOME"]ya da bu konuda CMD ["sh -c echo $HOME"]?
altmış4bit

4

Kendini zorlaştırma. Sadece "start.sh" olan bir bash dosyası oluşturun:

#!/bin/bash

/usr/bin/command2 param1
/usr/bin/commnad1

Dockerfile’nizde:

ADD start.sh /

CMD ["/start.sh"]

2

CMD(Ve RUNve ENTRYPOINT) ' nin json sözdizimi argümanları doğrudan çekirdeğe exec system sall olarak aktarır. Exec çağrısında, komutun boşluklardan bağımsız değişkenlerden ayrılması, tırnakların kaçması, IO yönlendirmeleri, değişkenlerin ikame edilmesi, komutlar arasında borulama, çoklu komutların çalıştırılması vb. Sistem sadece çalıştırılabilir dosyayı çalıştırır ve bu çalıştırılabilir öğeye iletilecek argümanların listesini alır ve çalıştırır.

Karakterler gibi $, değişkenler genişletmek için ;ayrı komutlara ayrı argümanları (boşluk), &&ve ||zincir komutlara, >çıkış yönlendirme için, |gibi kabuk ve ihtiyaç şeyin tüm özellikleri komutları arasında borusuna vb vardır /bin/shya /bin/bashyorumlamak ve bunları uygulamaktır.


Dize sözdizimine geçerseniz CMD, docker komutunuzu bir kabukla çalıştırır:

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

Aksi takdirde, ikinci sözdiziminiz de aynı şeyi yapar:

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

İlk komutunuz arızalanırsa, özellikle de arka planda çalışıyorsa, herhangi bir hata işleme olmadığından, bir kabın içinde bu şekilde birden fazla komut çalıştırmanın tavsiye edilmediğini unutmayın. Ayrıca, kabın içinde sinyal işlemeyi kıracak, 10 saniyelik bir gecikme ve konteynerin liman işçisi tarafından nezaketsiz öldürülmesiyle sonuçlanan kabın içinde 1 olarak çalışan bir kabuk bırakırsınız. Sinyal işleme, kabuk execkomutu kullanılarak hafifletilebilir :

CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm

Bununla birlikte, arka planda sessizce başarısız olan işlemlerle uğraşmak, süpervizör gibi bir çok işlem yöneticisine geçmenizi veya tercihen uygulamanızı birden çok kapsayıcıya bölmenizi ve bunları docker-compose gibi bir şeyle dağıtmanızı gerektirir.


1

DOCKER CMD formunda yalnızca ilk parametre yürütüldüğü için geri kalanı bu komuta beslendiği için ilk komutun başarısız olduğunu tahmin ediyorum.

İkinci form çalışır çünkü tüm komutlar ";" ile ayrılmıştır. onları yürüten sh komutuna beslenir.


1

"Başladıktan sonra" virgül koymanız gerektiğini sanmıyorum.

kullanmak yerine

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

Deneyin

CMD ["/etc/init.d/nullmailer", "start", "/usr/sbin/php5-fpm"]

liman işçisi "sh -c" kullandığından, yukarıdaki komut aşağıdaki gibi yürütülecektir

/etc/init.d/nullmailer start
/etc/init.d/nullmailer /usr/sbin/php5-fpm

Json sözdizimi komutları bir kabuk ile çalıştırmaz sh -c, bu senaryoda yoktur.
BMitch
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.