Синтаксис 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форму?