在 Docker 中使用 Laravel schedule

in 技术 with 0 comment

在 Docker 中部署 Laravel 应用,难免会用到 Laravel 本身的任务调度系统(Schedule),而 Schedule 需要用到 cron,在 Docker 中使用 cron,有以下三种方案:

在 PHP 容器中使用 cron

我们直接使用基于 Ubuntu 的 php:7.1.11-fpm的 Docker Hub 的官方镜像,然后需要在Dockerfile文件中安装 cron.

RUN apt-get install cron -y

然后在Dockerfile文件所在目录下创建crontab文件,内容为:

* * * * * /usr/local/bin/php /your_laravel_app_path/artisan schedule:run >> /dev/null 2>&1
其中your_laravel_app_path为 Laravel 应用在容器中的实际路径。

其实上面这一步我是踩了坑的,之前我一直按照官方手册的以下写法来配置的:

* * * * * php /your_laravel_app_path/artisan schedule:run >> /dev/null 2>&1

打了日志之后我才发现,容器内无法直接找到 PHP 的执行文件,所以要写全 PHP 执行文件的完整路径,例如/usr/local/bin/php。当然,PHP 执行文件的路径可能会有所不同,如果不清楚,需要到 PHP 容器中查看一下。

然后继续写Dockerfile,将crontab文件映射到容器目录中,赋予其读写权限:

COPY ./crontab /var/spool/cron/crontabs/root
RUN chmod 0644 /var/spool/cron/crontabs/root
RUN crontab /var/spool/cron/crontabs/root

至于第三行的命令,这么做是为了使 crontab 配置生效,我参考了 这篇文章,具体原因没有深究。

注意:如果容器文件系统是 Debian,cron 的配置路径是有所不同的,本文不赘述,这里只讨论 Ubuntu 的镜像

运行 cron

一开始我直接在Dockerfile中写了CMD ["cron"],发现 PHP-FPM 服务不启动了,是因为Dockerfile中只会执行一次 CMD 命令,多条 CMD 只执行最后一条,CMD ["cron"]CMD ["php-fpm"]覆盖了。

因此我们需要一个 bash 脚本来启动 cron,在Dockerfile文件所在目录下创建entrypoint.sh,文件内容为:

#!/bin/bash

set -e

cron

exec "$@"

然后使用ENTRYPOINT命令添加到Dockerfile就好。
完整的Dockerfile文件应该是这个样子:

######
# See: https://hub.docker.com/_/php/
######

FROM php:7.1.11-fpm

RUN apt-get update && apt-get install -y cron
RUN rm -rf /var/lib/apt/lists

COPY ./crontab /var/spool/cron/crontabs/root
RUN chmod 0644 /var/spool/cron/crontabs/root
RUN crontab /var/spool/cron/crontabs/root

COPY ./entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]

CMD ["php-fpm"]

重点结论

  1. 要在容器中使用 cron,需要在Dockerfile中安装 cron,并将 crontab 配置信息映射到容器内。
  2. crontab 配置 Laravel-scheduler 时,要填写 PHP 的执行文件路径,不然可能无法正确执行。
  3. 要写单独的脚本启动 cron,否则会覆盖掉 PHP 容器的 PHP-FPM 服务。
Responses
选择表情选择表情