概要
ローカル環境で、Laravelスケジュールを設定して、自動実行してみたくて調べたことをメモする。
ファイル構成
以下のようなファイル構成で構築してみる。
※ ソースコード:Github-reflet/laravel5.6
├ docker
│ ├ cron // ← cron実行する(PHP-CLI)
│ │ ├ cron.root
│ │ └ Dockerfile
│ │
│ └ php // ← Apacheから実行される(PHP-FPM)
│ ├ .dockerignore
│ ├ Dockerfile
│ ├ php.ini
│ └ www.conf
│
├ src // ← Laravel関連のフォルダ
│ ├ app
│ ...
│ └ yarn.lock
│
└ docker-compose.yml
cronコンテナについて
phpコンテナ内でcronを起動するのが簡単かと思ったが、意外とうまくいかない。
※ 下記に記載されている症状が発生... まあCMD変えたら、そらそうなるよね... (^^;)
→ PHPコンテナのDockerファイルでCMDを書くとnginxコンテナと接続できなくなった
そこで、PHPコンテナをベースにCRONコンテナを別途作成しました。
./docker/cron/Dockerfile
# PHP-FPMのイメージをベースに構築する
FROM my-laravel5.6/php:7.3
# cronインストール
RUN apt-get install -y cron
# cron設定を配置する
COPY ./docker/cron/cron.root /etc/cron.d/cron
# ログを標準出力へ出力できるようにシンボリックリンクを作成する
RUN chmod 0644 /etc/cron.d/cron && ln -sf /proc/1/fd/1 /var/log/cron.log
# フォアグラウンドでcronを起動する
CMD cron -f
cron設定について
crontabの設定は以下のようにしました。
./docker/cron/cron.root
* * * * * root /usr/local/bin/php /var/www/www.example.com/artisan schedule:run >> /var/log/cron.log 2>&1
※ シンボリックリンク ( /var/log/cron.log
)で、標準出力に接続する
docker-composeの設定について
以下のようにcronとphpコンテナの2つを起動するようにしてみました。
./docker-compose.yml
version: '3'
services:
php:
image: my-laravel5.6/php:7.3
build:
context: ./
dockerfile: ./docker/php/Dockerfile
tty: true
ports:
- '9000:9000'
volumes:
- src:/var/www/www.example.com:cached
- vendor:/var/www/www.example.com/vendor
- node_modules:/var/www/www.example.com/node_modules
depends_on:
- mysql
cron:
image: my-laravel5.6/cron:7.3
build:
context: ./
dockerfile: ./docker/cron/Dockerfile
tty: true
volumes:
- src:/var/www/www.example.com:cached
- vendor:/var/www/www.example.com/vendor
- node_modules:/var/www/www.example.com/node_modules
depends_on:
- php
...
volumes:
vendor:
node_modules:
src:
driver_opts:
type: none
device: ${PWD}/src
o: bind
サーバ起動
dockerを起動してみる。
$ docker-compose build
スケジュール設定
テストメール送信クラスを追加する。
$ docker-compose exec php php artisan make:mail TestEMail
テストメール送信のコマンドを追加する。
$ docker-compose exec php php artisan make:command EmailSendCommand
スケジュール設定を追加する。
./src/app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// ↓ 1分ごとに定期実行する
$schedule
->command('email:test') // 実行するコマンド
->everyMinute() // 実行間隔: 毎分
;
}
cron確認
テストメール送信する $ php artisan emai:test
コマンドを1分ごとに実行している。
下記コマンドにて、定期状況をログで確認してみる。
$ docker-compose logs cron
cron_1 | No scheduled commands are ready to run.
cron_1 | No scheduled commands are ready to run.
cron_1 | No scheduled commands are ready to run.
cron_1 | No scheduled commands are ready to run.
cron_1 | Running scheduled command: '/usr/local/bin/php' 'artisan' email:test > '/dev/null' 2>&1
cron_1 | Running scheduled command: '/usr/local/bin/php' 'artisan' email:test > '/dev/null' 2>&1
cron_1 | Running scheduled command: '/usr/local/bin/php' 'artisan' email:test > '/dev/null' 2>&1
cron_1 | Running scheduled command: '/usr/local/bin/php' 'artisan' email:test > '/dev/null' 2>&1
問題ないようですね。
参考資料
- Laravel 5.6 タスクスケジュール
- Docker + Cron環境を実現する3つの方法
- Laravelでschedule:runしたときのoutputがdockerで標準出力されない問題を解消
- LaravelにDockerファイルでcronを導入して定期的にメール送信する方法
以上