Dockerでcronを動かす
Dockerでcronを動かそうとしているのですが、設定したPGMが実行されない(原因不明)
alpineベースだとうまくいかないのかもなので、Debianベースで試してみようかな。
または公開されているcron用イメージを使ってみるとかか。
実装
docker-compose.yml
version: "3"
services:
# 上に色々なサービスが記載...
cron:
build: ./cron
volumes:
- ./cron/root:/var/spool/cron/crontabs/root
./cron/DockerFile
FROM alpine:3.14
# 必要パッケージの取得とタイムゾーンの変更処理(Asia/Tokyo)
ENV TZ=Asia/Tokyo
RUN apk update
RUN apk --no-cache add tzdata
# dockerのバイナリを取得し、クライアントのみを/usr/local/binへコピー
RUN apk add --no-cache ssl_client && \
mkdir -p /usr/local/bin && \
wget https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz -O - | tar -xzC /usr/local/bin --strip=1 docker/docker
# あらかじめ用意しておいたcrontabs用ファイルをコンテナへコピーする
RUN mkdir -p /var/spool/cron/crontabs
COPY root /var/spool/cron/crontabs/root
CMD crond -l 2 -f
./cron/root
* * * * * echo 'test' >> /var/log/test.log
* * * * * echo '=== environment variables ===' && env
状況
- cronコンテナに入りps auxで確認したところcrondは動いている
- cron自体の実行ログが出力されてない(/var/log/cron)
- cronで実行される「echo 'test' >> /var/log/test.log」で吐くはずのログが出力されていない(/var/log/test.log)
# ps aux
PID USER TIME COMMAND
1 root 0:00 busybox crond -l 2 -L /dev/stderr -f
8 root 0:00 /bin/sh
15 root 0:00 ps aux
$ docker-compose logs cron
Attaching to docker_cron_1
cron_1 | crond: crond (busybox 1.33.1) started, log level 2
cron_1 | crond: wakeup dt=15
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
cron_1 | crond: wakeup dt=60
分からない
- crondの設定ファイル(/etc/crontab)が存在しないがどこで設定されている?
- crondのログ出力場所の設定ってどこでやっている?(実行ログは/var/log/cronとネットで調べると出てくるがそのファイルが生成されてない)
alpineとは
- 組み込み系でよく使われているBusyBoxとmuslをベースにしたLinuxディストリビューション
- BusyBox + パッケージマネージャ(apk)
- busyboxとは:Alpine LinuxのベースとなっているLinuxのディストリビューション
willfarrell/crontabのイメージ使うことでうまくいった。
実装
docker-compose.yml
version: "3"
services:
# 上に色々なサービスが設定されている
cron:
build: ./cron
volumes:
- /var/run/docker.sock:/var/run/docker.sock
docker.sockについてはプルリクに上がっているため、今後指定しなくてもよくなりそう。
./cron/DockerFile
FROM willfarrell/crontab:1.0.0
COPY config.json ${HOME_DIR}/
./cron/config.json
[{
"schedule":"@every 1m",
"command":"echo 'test1111' >> /var/log/test.log"
},{
"comment": "laravel schedule:run",
"schedule":"* * * * *",
"command": "php artisan schedule:run",
"project": "docker",
"container": "php"
}]
ログ
$ docker-compose logs cron
Attaching to docker_cron_1
cron_1 | ##### crontab generation complete #####
cron_1 | */1 * * * * /bin/bash /opt/crontab/jobs/0aef401c-844a-4b01-bf56-1daa8553d5c5.sh
cron_1 | # laravel schedule:run
cron_1 | */1 * * * * /bin/bash /opt/crontab/jobs/b15b847d-ba9b-45c1-a4ae-ff45bd6a4775.sh
cron_1 | ##### run commands with onstart #####
cron_1 | crond -f -d 6 -c /etc/crontabs
cron_1 | crond: crond (busybox 1.31.1) started, log level 6
cron_1 | crond: USER docker pid 132 cmd /bin/bash /opt/crontab/jobs/0aef401c-844a-4b01-bf56-1daa8553d5c5.sh
cron_1 | crond: USER docker pid 133 cmd /bin/bash /opt/crontab/jobs/b15b847d-ba9b-45c1-a4ae-ff45bd6a4775.sh
cron_1 | Start Cronjob **0aef401c-844a-4b01-bf56-1daa8553d5c5** null
cron_1 | End Cronjob **0aef401c-844a-4b01-bf56-1daa8553d5c5** null
cron_1 | Start Cronjob **b15b847d-ba9b-45c1-a4ae-ff45bd6a4775** laravel schedule:run
cron_1 | [2021-10-29T04:07:01+00:00] Running scheduled command: Callback
cron_1 | End Cronjob **b15b847d-ba9b-45c1-a4ae-ff45bd6a4775** laravel schedule:run
config.jsonの設定(Laravelのタスクスケジューラの実行)
cronコンテナからphpコンテナに対してphp artisan schedule:runする場合
下記シェルスクリプトが実行されます。
#!/usr/bin/env bash
set -e
CONTAINERS=$(docker ps --format '{{.Names}}' | grep -E "^docker_php.[0-9]+")
for CONTAINER_NAME in $CONTAINERS; do
docker exec ${CONTAINER_NAME} php artisan schedule:run
done
「docker-php-1」に対して実行する場合 「project」は「docker」で
「container」は「php」にして下さい。
$ docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
docker-cron-1 "/sbin/tini -- /dock…" cron running (healthy)
docker-https-portal-1 "/init" https-portal running 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
docker-memcached-1 "docker-entrypoint.s…" memcached running 0.0.0.0:11211->11211/tcp
docker-mysql-1 "docker-entrypoint.s…" mysql running 0.0.0.0:3306->3306/tcp
docker-nginx-1 "/docker-entrypoint.…" nginx running 80/tcp
docker-php-1 "docker-php-entrypoi…" php running 9000/tcp
./cron/config.json
[{
"schedule":"@every 1m",
"command":"echo 'test1111' >> /var/log/test.log"
},{
"comment": "laravel schedule:run",
"schedule":"* * * * *",
"command": "php artisan schedule:run",
"project": "docker",
"container": "php"
}]
docker-composeで、自動生成されるコンテナ名がローカルと本番サーバで異なる事象が起き
cronコンテナ→phpコンテナに入れずcronが実行されなかった。
(ローカル:docker_php_1 本番:docker-php-1になっていた。container_nameは未指定のためコンテナ名は自動生成)
ログ
ローカル
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------------------------------------
docker_cron_1 /sbin/tini -- /docker-entr ... Up (healthy)
docker_https-portal_1 /init Up 0.0.0.0:443->443/tcp,:::443->443/tcp, 0.0.0.0:80->80/tcp,:::80->80/tcp
docker_memcached_1 docker-entrypoint.sh memcached Up 0.0.0.0:11211->11211/tcp,:::11211->11211/tcp
docker_mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp
docker_nginx_1 /docker-entrypoint.sh ngin ... Up 80/tcp
docker_php_1 docker-php-entrypoint php-fpm Up 9000/tcp
本番
$ docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
docker-cron-1 "/sbin/tini -- /dock…" cron running (healthy)
docker-https-portal-1 "/init" https-portal running 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
docker-memcached-1 "docker-entrypoint.s…" memcached running 0.0.0.0:11211->11211/tcp
docker-mysql-1 "docker-entrypoint.s…" mysql running 0.0.0.0:3306->3306/tcp
docker-nginx-1 "/docker-entrypoint.…" nginx running 80/tcp
docker-php-1 "docker-php-entrypoi…" php running 9000/tcp
コンテナ名の自動生成ルール
docker-composeでcontainer_nameを指定するとそのコンテナ名で生成される。
container_name を指定しない場合はCOMPOSE_PROJECT_NAME 変数 + _ + サービス名 + _ + 連番
対応
container_nameを指定(docker_php_1)
※docker_php.[0-9]+
に合わせる({project}_{container}.[0-9]+)
config.json
[{
"comment": "laravel schedule:run",
"schedule":"* * * * *",
"command": "php artisan schedule:run",
"project": "docker",
"container": "php"
}]
#!/usr/bin/env bash
set -e
CONTAINERS=$(docker ps --format '{{.Names}}' | grep -E "^docker_php.[0-9]+")
for CONTAINER_NAME in $CONTAINERS; do
docker exec ${CONTAINER_NAME} php artisan schedule:run
done
docker-compose.yml
version: "3"
services:
php:
container_name: 'docker_php_1'
build: ./php
volumes:
- ../src:/usr/share/nginx/html
- ./php/php.ini:/usr/local/etc/php/conf.d/php.ini
depends_on:
- "mysql"
- "memcached"
# 省略
cron:
container_name: 'docker_cron_1'
build: ./cron
volumes:
- /var/run/docker.sock:/var/run/docker.sock