Docker CMD yönergesinde birden çok komut

Dockerfile'daki CMD yönergesi aracılığıyla çalışma zamanında iki komut çalıştırmaya çalıştığımda neler olduğunu anlamıyorum. Bunun işe yaraması gerektiğini düşündü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 zorundaydım.:

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

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

Sadece not etmek için - aynı şey command: yönerge docker-compose.yml beklendiği gibi.

Aradaki farkın, ikinci komutun kabuk işlemesi yapması ve ilkinin yapmaması nedeniyle olabileceğine inanıyorum. Başına resmi belgeler vardır exec ve shell form. İlk komutunuz bir exec form. Bu exec form, ortam değişkenlerini genişletmezken shell form öyle. Bu kullanarak mümkündür exec form komut kabuk işleme bağımlılığı nedeniyle başarısız oluyor. Bunu çalıştırarak kontrol edebilirsiniz docker logs CONTAINERID

İkinci komutunuz olan kabuk formu aşağıdakilere eşdeğerdir: -

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

Belgelerden alıntılar -

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

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

#!/bin/bash/usr/bin/command2 param1/usr/bin/command1

docker Dosyanızda şunları yapın:

ADD start.sh /RUN chmod +x /start.shCMD ["/start.sh"]

Json sözdizimi CMD (ve RUN ve ENTRYPOINT) argümanları doğrudan çekirdeğe bir exec syscall olarak iletin. Exec syscall'da komutun bağımsız değişkenlerden boşluklarla ayrılması, tırnak işaretlerinden kaçması, GÇ yeniden yönlendirmesi, değişken değiştirme, komutlar arasında geçiş yapma, birden çok komut çalıştırma vb. Yoktur. Syscall yalnızca yürütülebilir dosyayı çalıştırmak ve bu yürütülebilir dosyaya geçirilecek bağımsız değişkenlerin listesini alır ve çalıştırır.

Gibi karakterler $ değişkenleri genişletmek için, ; komutları ayırmak için, (boşluk) bağımsız değişkenleri ayırmak için, && ve || komutları zincirlemek için, > çıktı yeniden yönlendirmesi için, | komutlar arasında geçiş yapmak vb. Kabuğun tüm özellikleridir ve aşağıdaki gibi bir şeye ihtiyaç duyar /bin/sh veya /bin/bash bunları yorumlamak ve uygulamak.


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

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

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

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

İlk komutunuz başarısız olursa, özellikle arka planda çalışıyorsa, hata işleme olmadığından, bir kapsayıcı içinde bu şekilde birden çok komut çalıştırmanızı önermediğimi unutmayın. Ayrıca, kabın içinde pıd 1 olarak çalışan bir kabuk bırakırsınız, bu da sinyal işlemeyi kıracak ve 10 saniyelik bir gecikmeye ve konteynerinizin docker tarafından nankör bir şekilde öldürülmesine neden olacaktır. Sinyal işleme, kabuk kullanılarak hafifletilebilir exec komut:

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

Bununla birlikte, arka planda sessizce başarısız olan işlemleri işlemek, supervisord gibi bir tür çoklu işlem yöneticisine geçmenizi veya tercihen uygulamanızı birden çok kapsayıcıya ayırmanızı ve bunları docker-compose gibi bir şeyle dağıtmanızı gerektirir.

Sanırım ilk komut başarısız oluyor çünkü DOCKER CMD formunda sadece ilk parametre çalıştırılıyor, gerisi bu komuta besleniyor.

İkinci form, ";" ile ayrılmış tüm komutlar, bunları yürüten sh komutuna beslendiğinden çalışır.

Örneğin, çalıştırmanız gereken iki python komutunuz olduğunu düşünün python init_reset.py ve python app.py. Ardından cmd'yi kullanarak iki komutu tek komutla birleştirebilirsiniz

CMD python init_reset.py ; python app.py

Docker compose , bu aşağıdaki örnek olarak yapılabilir:

command: ["sh", "-c", "    apt update && apt install -y libldap-common;    cp /ca.crt /usr/local/share/ca-certificates/;    update-ca-certificates;    exec apache2-foreground  "]

Bu exec ana yürütülebilir dosyanın bağlamını apache2-forground'a geçirir.

"Başlat" dan sonra yarı virgül koymanız gerektiğini düşünmüyorum.

kullanmak yerine

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

denemek

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

docker "sh -c" kullandığından, yukarıdaki komut aşağıdaki gibi çalıştırılacaktır

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