У меня есть докер, который использует два контейнера: nginx и php7-fpm. Я создаю php через Dockerfile, и мне нужно, чтобы на нем был установлен cron:
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log // this line is breaking things
Таким образом, nginx сообщает об ошибке 502 Bad Gateway. Если я удалю последнюю строку CMD, все будет работать нормально. Как я могу это исправить?
Я также столкнулся с тем же вопросом при использовании докера с php-fpm
и nginx
. Я решил проблему аналогично ответу, данному ранее.
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && docker-php-entrypoint php-fpm
Добавление последней строки для запуска процесса, который php-fpm
предназначен для запуска
Как указано выше,
В контейнере докера у вас может быть только одна точка входа или команда, выполняемая при запуске контейнера.
Но когда вы добавляете нашу собственную точку входа в контейнер докера, выполняя CMD ["custom_script.sh"]
или ENTRYPOINT ["custom_script.sh"]
, сценарий точки входа по умолчанию заменяется вашим пользовательским (в нашем случае custom_script.sh
).
Я нашел решение проблемы, написав сценарий таким образом, чтобы не заменять оригинал, а расширять.
docker-compose ps
после запуска контейнера без сценария точки входа. Результат на моей машине выглядит так: Name Command State Ports
----------------------------------------------------------------------------------------------------------------
appointmentlaravel_appointment_app_1 docker-php-entrypoint php-fpm Up 0.0.0.0:9007->6001/tcp, 9000/tcp
Как видите, по умолчанию контейнер скрипта запускается как docker-php-entrypoint php-fpm
так.
# arbitary code to run when docker-container starts
docker-php-entrypoint php-fpm
В вашем случае dockerfile
может выглядеть;
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
CMD cron && docker-php-entrypoint php-fpm
Посмотрите, как я заменил последнюю строку вашего файла докеров на запуск docker-php-entrypoint php-fpm
.
В контейнере докера у вас может быть только одна точка входа или команда, выполняемая при запуске контейнера. Когда у вас в конце Dockerfile:
CMD cron && tail -f /var/log/cron.log
Это означает, что единственная команда, которая будет запущена, - это cron. Таким образом, ваша начальная точка входа для службы php-fpm становится неактуальной. Чтобы запустить несколько процессов в контейнере докера, вы должны использовать сценарий-оболочку или супервизор. Для сценария-оболочки напишите его и скопируйте в процессе сборки. В сценарии должны быть команды запуска для всех ваших служб.
В CMD будет что-то вроде:
CMD ./wrapper_script.sh
Для супервизора в Интернете доступны хорошие учебные пособия, в которых объясняется, как использовать супервизор с докером.
Ваш Dockerfile будет выглядеть так:
FROM 'php:7-fpm'
# PDO
RUN docker-php-ext-install pdo_mysql
# Cron
RUN apt-get update -q -q && apt-get install -y cron supervisor
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN touch /var/log/cron.log
ADD supervisord.conf /etc/supervisor.conf
ENTRYPOINT ["/usr/bin/supervisord -c /etc/supervisor.conf"]
Затем создайте файл supervisord.conf:
[supervisord]
nodaemon=true
[program:php-fpm]
command=php-fpm-commands
[program:cron]
command=cron-commands
Замените php-fpm-commands и cron-commands на команды и параметры, которые необходимы для каждой службы.