スケジューラー、環境、ユーザー、時刻、または必要なランタイムパスが稼働中のホスト環境と異なると、コンテナ内のスケジュール済みジョブは失敗します。
対話型のホストシェルで成功するコマンドは、ホストのPATH、ログインプロファイル、タイムゾーン、マウントされたファイル、認証情報、DNS、または常駐するcronデーモンに依存している可能性があります。コンテナ内では、これらが保証されるとは限りません。まずスケジューラープロセスが稼働していることを確認し、次にcronが使用するものと同じ最小限の環境およびユーザーで、ジョブを正確に実行します。
スケジューラープロセスが実際に実行されていることを確認する
コンテナ内で実行中のプロセスと起動コマンドを確認します。イメージにcronパッケージをインストールしただけではデーモンは起動せず、通常、コンテナは設定されたエントリーポイントまたはコマンドだけを実行します。
Stack Overflowで長く議論されているDocker cronの問題では、ホストのサービスがコンテナ内のcrontabを制御すると想定せず、コンテナ内でスケジューラーを実行する必要性が中心となっています。最初に確認すべきなのは、スケジュール時刻になったときにcronプロセスが稼働しているかどうかです。
スケジューラーが実行されていない場合は、意図を明確にした設計を選びます。cronまたはコンテナ対応のスケジューラーをフォアグラウンドプロセスとして実行する、専用のジョブコンテナを使用する、またはホストのcronからアプリケーションコンテナを呼び出します。ログの記録方法と停止方法を決めないまま、管理されていない2つ目のデーモンを追加しないでください。
最小限の環境で正確なコマンドを実行する
スケジュールされたコマンドをコピーし、意図したジョブユーザーとして、環境を削減した状態でコンテナ内で実行します。標準出力、標準エラー、終了コード、現在のディレクトリ、環境変数を記録します。
コンテナ内のcronジョブは、PATH、言語ランタイム、APIトークン、アプリケーション変数を提供していた対話型シェルのプロファイルをcronが読み込まないために失敗することがよくあります。コンテナ向けのスケジューラーガイドでは、Docker Composeジョブに必要なジョブ環境を維持することを主要な要件として挙げています。
最小限の環境でのみコマンドが失敗する場合は、絶対パスと必要最小限の変数を明示的に追加します。関係のないエイリアス、プロンプト、シークレットを持ち込む完全なユーザープロファイルの読み込みは避けてください。
PATH、シェル、作業ディレクトリ、ユーザーを確認する
相対コマンドや相対ファイルパスを絶対パスに置き換えます。選択したシェルが存在すること、またcrontabの構文がイメージにインストールされているcron実装と一致していることを確認します。
設定されたcronユーザーとしてジョブを実行し、スクリプト、設定、ソケット、出力ディレクトリに対する読み取り、書き込み、実行権限をテストします。root権限で手動テストが成功しても、権限のないスケジュール済みジョブが完了できることの証明にはなりません。
コマンドまたはラッパースクリプト内で作業ディレクトリを設定します。ディレクトリまたはユーザーだけを変更してジョブが成功する場合は、コンテナのデフォルト設定に依存せず、その明示的なコンテキストをバージョン管理された設定に残します。
コンテナの時刻とタイムゾーンをスケジュールと比較する
コンテナ内で現在時刻、タイムゾーン、次回の実行予定時刻を表示します。コンテナはホストのカーネルクロックを共有しますが、表示やcronの解釈にはUTCまたは異なるタイムゾーンファイルを使用する場合があります。
Server Faultの事例では、ホストが現地時刻を表示していてもコンテナの時刻が別のタイムゾーンで表示されることがあり、その結果、正しいcrontabが見かけ上の現地時刻とは異なる時間に実行されることが示されています。
タイムゾーン戦略を1つ明示的に選び、コンテナを再作成した後に検証します。基盤となるタイムゾーンを曖昧なままcron式の時刻だけをずらして調整しないでください。夏時間やイメージの変更によって、再び実行時刻がずれる可能性があります。
マウント、シークレット、ネットワークアクセス、コンテナの存続期間を確認する
すべての入力ディレクトリ、出力パス、シークレット、ソケット、設定ファイルが、実行時にコンテナ内に存在することを確認します。次に、同じコンテナネットワークからDNS、データベース、API、NASへアクセスできることをテストします。
ホストのcronは、コンテナ内には存在しないホストのパスを参照できます。Nextcloud Dockerの事例では、バックグラウンドジョブが設定済みに見えても、実際のコンテナコマンド、ユーザー、またはアプリケーションパスが期待されるバックグラウンド実行を妨げる可能性が示されています。
また、スケジュール時刻になったときにコンテナが稼働し続けていることも確認します。短時間で終了するアプリケーションコンテナやデプロイによる置き換えによって、長時間かかるジョブや実行頻度の低いジョブが完了する前に内部スケジューラーが終了することがあります。
スケジューリングの境界を1つに定め、無人で実行されることを検証する
スケジュールの管理者を1つにします。ホストのcronからdocker execを呼び出す、専用のスケジューラーコンテナを使用する、またはアプリケーションイメージ内でフォアグラウンドのスケジューラーを実行する方法があります。スケジューラーを重複させると、同じメンテナンスタスクが2回実行される可能性があります。
ZimaSpaceのコンテナ側のDNSテストガイドでは、スケジューラーは起動しているものの別のサービスに接続できない場合に発生する、下流側の原因の1つを説明しています。
問題が解決したといえるのは、コンテナの再作成後およびホストの再起動後に、意図した時刻にジョブが実行され、ログが記録され、想定したユーザーとパスが使用され、アプリケーションで検証済みの結果が生成された場合だけです。手動コマンドが成功することは、完了の判定基準ではありません。
サポートとヒント
もっと読む

Dockerボリュームの復元でファイルの内容は再現されるのに、拡張属性が失われるのはなぜですか?
xattr のインベントリ、tar と Rsync のオプション、名前空間、保存先のサポート状況、権限、ラベル、アプリメタデータ、テストを網羅したボリューム復元の診断。

Composeファイルを変更した後も、実行中のコンテナが古いメモリ制限を維持するのはなぜですか?
ライブcgroup、再起動と再作成の違い、Composeのフィールド、ハードリミットとソフトリミット、親スコープ、スワップ、ランタイムヒープを網羅したメモリ制限の診断。

リバースプロキシを再起動すると、1つのセルフホストアプリですべてのセッションが無効になるのはなぜですか?
再起動の範囲、Cookieの所有権、シークレットのローテーション、キャッシュを利用したセッション、スティッキールーティング、認証ゲートウェイ、復旧を網羅したセッション喪失の診断。

