はじめに
oki2a24/sample_dockerized_laravel6: Laravel6 を Docker 化するサンプルです。 にて Laravel を Docker コンテナ化しました。
Apache 入りの PHP コンテナで Laravel を動かしています。この Laravel で タスクスケジュール 6.x Laravel も行いたいと思いました。
cron を動かせば簡単です。
しかし、 コンテナではすでに Apache のプロセスが動いており、ここに cron を足せません。
これを、なんとかしたのが本投稿となります。
まとめ
- プロセス管理ツール Supervisor を使い、コンテナ内で複数のプロセスを管理する。
- feat: Supervisor を使って php apache と cron を 1 つのコンテナ内で動かす by oki2a24 · Pull Request #14 · oki2a24/sample_dockerized_laravel6
ステップ 1. Supervisor で今まで動いている apache2-foreground を動かす
次を足しました。
Dockerfile
RUN apt-get update && apt-get install -y \
supervisor \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir -p /var/log/supervisor
COPY ./docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord"]
docker/supervisord.conf
[supervisord]
nodaemon=true
[program:apache2]
command=/usr/local/bin/apache2-foreground
apache2-foreground
の特定方法は、 php/Dockerfile at master · docker-library/php を当たりました。
そして、コンテナ内で apache2-foreground
のパスを type コマンドで特定いたしました。
cron をインストールするのをコンテナ内で試す
busybox-static
をインストール/var/spool/cron/crontabs/root
という cron 設定ファイルを設置
apt update && apt install -y busybox-static
cat <<'EOT' > /var/spool/cron/crontabs/root
* * * * * echo '=== hello! ==='
EOT
busybox crond -L /var/log/cron
/var/log/cron
に毎分指定した内容が実行されていることが確認できました。ただし、指定した内容の結果は、分かりませんでした。
cron を Supervisor に登録して動かす時に直面した問題
/var/spool/cron/crontabs/root
* * * * * echo '=== environment variables ===' && env
/etc/supervisor/conf.d/supervisord.conf
には次を追記。
[program:crond]
command=/bin/busybox crond -L /dev/stderr
docker-compose logs -f の結果をみると、 cron が複数立ち上がってしまっていました。
app_1 | /usr/lib/python2.7/dist-packages/supervisor/options.py:461: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
app_1 | 'Supervisord is running as root and it is searching '
app_1 | 2020-04-25 12:11:21,788 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root in the config file to avoid this message.
app_1 | 2020-04-25 12:11:21,788 INFO Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
app_1 | 2020-04-25 12:11:21,796 INFO RPC interface 'supervisor' initialized
app_1 | 2020-04-25 12:11:21,796 CRIT Server 'unix_http_server' running without any HTTP authentication checking
app_1 | 2020-04-25 12:11:21,796 INFO supervisord started with pid 1
app_1 | 2020-04-25 12:11:22,801 INFO spawned: 'cron' with pid 9
app_1 | 2020-04-25 12:11:22,804 INFO spawned: 'apache2' with pid 10
app_1 | 2020-04-25 12:11:22,807 INFO exited: cron (exit status 0; not expected)
app_1 | 2020-04-25 12:11:23,901 INFO spawned: 'cron' with pid 27
app_1 | 2020-04-25 12:11:23,902 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
app_1 | 2020-04-25 12:11:23,907 INFO exited: cron (exit status 0; not expected)
app_1 | 2020-04-25 12:11:25,915 INFO spawned: 'cron' with pid 29
app_1 | 2020-04-25 12:11:25,922 INFO exited: cron (exit status 0; not expected)
app_1 | 2020-04-25 12:11:28,934 INFO spawned: 'cron' with pid 31
app_1 | 2020-04-25 12:11:28,941 INFO exited: cron (exit status 0; not expected)
app_1 | 2020-04-25 12:11:29,945 INFO gave up: cron entered FATAL state, too many start retries too quickly
原因は、 cron をバックグランドで立ち上げたことでした。
Supervisor で管理したいプログラムはフォアグランドで動かすと良いようです。
- Dockerでsupervisorを使う時によくハマる点まとめ|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
- Subprocesses — Supervisor 4.1.0 documentation
気づいた問題点。 crond の実行ログを docker のログに出力するようにしたと思ったが、出力されていいない。
- Supervisor 設定で cron 実行ログは
/dev/stdout
を指定したが、 Docker のログに出てこない。 - Nginx イメージ方式にしてみる。つまり、ログファイルはコンテナ内に作り、これに
/dev/stdout
へのシンボリックリンクを貼る。
が、ダメ。
もしかしたら Supervisor が原因かもしれません。後回しにします。
ステップ2. Supervisor で cron も動かす
- cron は busybox 実現できた diff のみ記します。
$ git diff --cached
diff --git a/Dockerfile b/Dockerfile
index 5b449f6..49966d9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,11 +23,14 @@ RUN a2dissite 000-default \
&& a2ensite 001-my
ENV APP_ENV laravel
RUN apt-get update && apt-get install -y \
+ busybox-static \
supervisor \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir -p /var/log/supervisor
COPY ./docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
+COPY ./docker/crontabs/root /var/spool/cron/crontabs/root
+RUN ln -sf /dev/stdout /var/log/cron
CMD ["/usr/bin/supervisord"]
FROM composer:1.10.5 AS composer
diff --git a/docker/crontabs/root b/docker/crontabs/root
new file mode 100644
index 0000000..39dd8da
--- /dev/null
+++ b/docker/crontabs/root
@@ -0,0 +1 @@
+* * * * * cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1
diff --git a/docker/supervisord.conf b/docker/supervisord.conf
index 73f0cef..a8662f9 100644
--- a/docker/supervisord.conf
+++ b/docker/supervisord.conf
@@ -3,3 +3,6 @@ nodaemon=true
[program:apache2]
command=/usr/local/bin/apache2-foreground
+
+[program:crond]
+command=/bin/busybox crond -f -L /var/log/cron
$
おわりに
ログ出力に問題が残りましたけれども、 1 コンテナ内で Apache と cron を動かすことができました。
以下、他の参考ページです。
以上です。