トラブルシューティング · Docker
Docker コンテナの cron が動かない?実際に効く修正方法
Docker コンテナ内の cron がサイレントに失敗する理由 — PID 1、環境変数の消失、MTA なし — とそれぞれの修正方法。
コンテナ内で cron を動かすと、コンテナは通常の VM ではないため問題が起きやすいです。よくある原因を修正方法と合わせて紹介します。
1. cron が PID 1 として動いていない
コンテナはフォアグラウンドプロセスを1つだけ実行します。CMD でアプリを起動した場合、cron は決して起動しません。CMD が cron でも、デーモン化するためすぐに終了することがあります。フォアグラウンドで実行してください。
# Debian/Ubuntu ベース
CMD ["cron", "-f"]
cron とアプリを両方動かすには、小さなスーパーバイザー(supervisord、s6)またはプロセスマネージャーを使ってください — シェルの CMD でのバックグラウンド化には頼らないでください。
2. cron では環境変数が消える
これが最大の原因です。Docker は環境変数を PID 1 に注入しますが、cron はクリーンな環境でジョブを起動するため、DATABASE_URL や API キーが消えています。起動時にコンテナの環境変数をファイルにダンプして、ジョブで source してください。
CMD printenv | sed 's/^\(.*\)$/export \1/' > /etc/container.env && cron -f
# crontab 内で
0 * * * * . /etc/container.env && /app/run.sh
3. crontab には正しいフォーマットと末尾の改行が必要
システム crontab の行にはユーザー列が必要で、ファイルは改行で終わらないと最後のジョブが無視されます。
# /etc/cron.d/app — 「root」ユーザーフィールドに注意
0 2 * * * root /app/run.sh >> /var/log/cron.log 2>&1
COPY app-cron /etc/cron.d/app
RUN chmod 0644 /etc/cron.d/app && crontab /etc/cron.d/app
4.「cron がメールを送れない」— MTA がない
よくあるパターン: コンテナの crontab が出力をメールしようとしても MTA がないため、ジョブが「失敗」しているように見えます。ローカルメールに依存しないでください。docker logs に記録されるよう stdout にリダイレクトしてください。
0 2 * * * root /app/run.sh > /proc/1/fd/1 2>/proc/1/fd/2
5. 出力を確認する
docker logs -f <container>
docker exec -it <container> sh -c "crontab -l"
本当の問題: コンテナは再起動し、cron は忘れる
再デプロイ、OOM kill、クラッシュループ — これらはどれもコンテナ内の cron を停止させる可能性があり、何も教えてくれません。コンテナの外から監視することが唯一の信頼できるシグナルです。
ジョブが成功したときにハートビート URL に ping してください。コンテナがダウンしているかジョブが発火を停止した場合、ping が欠落してアラートが届きます。
HEALTHCHECK --interval=5m --timeout=10s \
CMD curl -fsS https://ping.steadycron.com/<your-ping-token> || exit 1