Синтаксис json CMD
(и RUN
и ENTRYPOINT
) передает аргументы ядру напрямую как системный вызов exec. В системном вызове exec нет разделения команды на аргументы пробелами, экранирования кавычек, перенаправления ввода-вывода, подстановки переменных, передачи между командами, выполнения нескольких команд и т. Д. Системный вызов принимает только исполняемый файл и список аргументов для передачи этому исполняемому файлу, и он запускает его.
Символы, такие как $
расширение переменных, ;
разделение команд,
(пробел) для разделения аргументов &&
и ||
цепочка команд, >
для перенаправления вывода, |
передачи между командами и т. Д., Являются функциями оболочки и нуждаются в чем-то вроде /bin/sh
или /bin/bash
для их интерпретации и реализации.
Если вы переключитесь на строковый синтаксис CMD
, docker запустит вашу команду с оболочкой:
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
Однако для обработки процессов, которые молча терпят неудачу в фоновом режиме, требуется переключиться на какой-нибудь многопроцессный менеджер, например supervisord, или, предпочтительно, разбить ваше приложение на несколько контейнеров и развернуть их с помощью чего-то вроде docker-compose.
exec
форму, так как она является предпочтительной? Почему это предпочтительнее? Или я должен использовать более простуюshell
форму?