Назад | Перейти на главную страницу

PHP7-FPM Docker CMD приводит к ошибке 502 Nginx

У меня есть докер, который использует два контейнера: 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. Я решил проблему аналогично ответу, данному ранее.

TL; DR

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 на команды и параметры, которые необходимы для каждой службы.