PHP7-FPM Docker CMD 导致 502 Nginx 错误

PHP7-FPM Docker CMD 导致 502 Nginx 错误

我有一个使用两个容器的docker compose:nginx和php7-fpm。我正在通过Dockerfile构建php,并且需要在其上安装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,一切正常。我该如何修复这个问题?

答案1

在 docker 容器中,启动容器时只能执行一个入口点或命令。在 Dockerfile 末尾添加以下内容:

CMD cron && tail -f /var/log/cron.log

这意味着唯一要运行的命令是 cron。因此,php-fpm 服务的初始入口点变得无关紧要。为了在 docker 容器中启动多个进程,您必须使用包装器脚本或主管。对于包装器脚本,请编写它并通过构建过程复制。该脚本应包含所有服务的启动命令。

CMD 将会有类似如下的内容:

CMD ./wrapper_script.sh

对于 Supervisor,网上有很多很好的教程,解释如何将 Supervisor 与 docker 结合使用。

你的 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 替换为每个服务所需的命令和选项。

答案2

php-fpm我在使用docker with和时也遇到了同样的问题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添加最后一行以启动要运行的进程


如上所述,

在docker容器中,启动容器时只能有一个入口点或一个执行的命令。

问题

CMD ["custom_script.sh"]但是当您通过执行或将我们自己的入口点添加到docker容器时ENTRYPOINT ["custom_script.sh"],默认入口点脚本将被您的自定义脚本替换(在我们的例子中custom_script.sh)。

我找到的解决问题的方法是编写脚本,不替换原始脚本,而是进行扩展。

解决方案

  • 要了解 docker 容器默认运行哪个脚本,请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

看看我如何将 dockerfile 的最后一行替换为运行docker-php-entrypoint php-fpm

答案3

user460778 的答案是正确的,容器只能有一个入口点,这里应该是 php-fpm 服务,所以你需要从主管运行 crons。我的主管文件如下所示

[supervisord]
nodaemon=true

[program:php-fpm]
command = /usr/local/sbin/php-fpm
autostart=true
autorestart=true

[program:cron]
autorestart=false
command=cron -f

相关内容