Синтаксис json CMD
(і RUN
і ENTRYPOINT
) передає аргументи ядра безпосередньо як exec syscall. Не відбувається відокремлення команди від аргументів пробілами, уникнення лапок, перенаправлення вводу-виводу, зміна підстановок, конфігурування між командами, виконання декількох команд тощо у системі exec syscall. Система syscall бере лише виконуваний файл для запуску та списку аргументів, які передаються цьому виконуваному файлу, і він запускає його.
Символи люблять $
розширювати змінні, ;
розділяти команди,
(пробіл) для розділення аргументів &&
і ||
ланцюгових команд, >
для перенаправлення виводу, |
передачі між командами тощо, - все це функції оболонки і потрібно щось на зразок /bin/sh
або /bin/bash
інтерпретувати та реалізовувати.
Якщо ви перейдете на синтаксис рядка CMD
, докер виконує вашу команду з оболонкою:
CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm
В іншому випадку ваш другий синтаксис робить саме те саме:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
Зауважте, що я не рекомендую запускати кілька команд таким чином всередині контейнера, оскільки немає помилок, якщо ваша перша команда не працює, особливо якщо вона працює у фоновому режимі. Ви також залишаєте оболонку, що працює як Pid 1, всередині контейнера, що порушить обробку сигналу, що призведе до затримки на 10 секунд і несамовитого вбивства вашого контейнера докером. Обробку сигналу можна пом'якшити за допомогою команди оболонки exec
:
CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm
Однак безперебійне оброблення процесів у фоновому режимі вимагає переключення на якийсь менеджер багатопроцесових процесів, як нагляд, або бажано розбивати додаток на декілька контейнерів і розгортати їх із чимось на зразок докер-композиції.
exec
форму, оскільки вона є бажаною формою? Чому це віддається перевазі? Або я повинен використовувати більш простуshell
форму?