feat(container): 古いイメージの自動リフレッシュと公開イメージのpull対応#7
Conversation
v2.2.0 で公式レジストリ固定の概念は廃止されているため、 クイックスタートのコメントを「サンプルレジストリ devbasex/devbase-samples は自動登録済み」に修正。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
devbase up 時のイメージ事前チェック (_ensure_images) を強化: 1. build: 定義あり / イメージが7日以上古い場合 → devbase build --no-cache で再ビルド 2. image: のみ (build: なし) / イメージが存在しない場合 → docker pull で取得 3. image: のみ / イメージが7日以上古い場合 → docker pull で再取得 実装: - _IMAGE_MAX_AGE_DAYS = 7 を定数化 - _get_image_age_days(): docker image inspect の Created を解析 Docker のナノ秒精度 RFC3339 を Python 3.10 の fromisoformat 互換形式に正規化 - _run_pull(image_name): docker pull の実行 - _run_build(no_cache=False): bash の cmd_build に --no-cache を透過 Bash 側 cmd_build は既に --no-cache をサポート済みのため変更不要。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
--no-cache フラグだけでビルド時にキャッシュは使われないため、 docker builder prune -af は冗長。さらに、prune は - 未使用キャッシュ (-a) を含むホスト全体の buildx キャッシュを削除 - 他プロジェクトの build キャッシュも巻き添えに する副作用があり、特に PR #7 で導入した自動 --no-cache 再ビルド (7日経過時) では意図せぬ全消去を引き起こす。 最小驚きの原則に従い、--no-cache はその build のみに作用するよう 修正。ステップ番号を [1/3]-[3/3] から [1/2]-[2/2] に整合化。 ディスク容量整理が必要な場合は別コマンド (devbase clean 等) で 明示的に行うべき。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #7 の self-review で挙げた MED/LOW 指摘を反映: - [MED] datetime / timezone / re を関数内 import からモジュール先頭へ移動 Python 標準ライブラリの軽量モジュールを関数内 import するのは非慣用。 - [MED] 閾値を環境変数 DEVBASE_IMAGE_MAX_AGE_DAYS で上書き可能に _image_max_age_days() ヘルパを追加。不正値 (非数値・負数) は 警告ログを出してデフォルト 7 にフォールバック。 - [LOW] RFC3339 タイムスタンプ整形を re.sub で簡潔化 split('.') + rfind('+/-') の手作業ロジックを 1 行の正規表現に。 ナノ秒/マイクロ秒/ミリ秒/小数なし/オフセット付き全パターン動作確認済み。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
レビュー指摘対応サマリー (commit 9010cbd)self-review で挙げた 4 件のうち、3 件を対応・1 件を見送り。
自己テスト結果CI 再実行結果全 5 チェック PASS(Ruff lint / ShellCheck / Python syntax 3.10-3.12)。 修正ファイル
|
Codex 第二意見レビューで指摘された 4 件に対応:
[1.1 HIGH] 公開イメージの定期 re-pull を廃止
docker image inspect の Created はイメージのビルド日時で
ローカル pull 日時ではないため、age 比較で再 pull すると
毎回 pull がループする欠陥があった。image-only サービス
(build: なし) は不在時のみ pull し、定期再 pull は行わない
方針に変更。「image: のみで定期 pull が必要」というユース
ケースが出てきたら別 PR で digest 比較等を実装する。
[1.2 HIGH] DEV_SERVICE_NAME 連動の build に修正
Python 側 _ensure_images() は get_dev_service_name() で対象
サービスを解決していたが、Bash 側 cmd_build は
'docker compose build dev' を固定実行していた。
DEV_SERVICE_NAME != dev なプロジェクトで自動再ビルド経路に
入ると存在しないサービスをビルドしようとして失敗する回帰。
Bash 側を 'docker compose build "${DEV_SERVICE_NAME:-dev}"'
に変更してチェックと実行のサービス名解決を整合化。
[1.4 MED] エラーメッセージを build/pull 双方を案内する文面に
_ensure_images() 失敗時に常に "devbase container build" を
案内していたが、image-only サービスでは build は不適切。
build と docker pull の両方を案内する文面に変更。
[2.1 MED] cli-reference.md に自動 build/pull 動作を明記
devbase up が条件次第で build/pull を自動実行する旨と、
DEVBASE_IMAGE_MAX_AGE_DAYS 環境変数の存在を追記。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex 第二意見レビュー 対応サマリー (commit 23e4e9e)外部 AI (Codex / gpt-5.4) で独立レビューを実施し、HIGH 3 件・MED 9 件・LOW 3 件の指摘を取得。本コミットでは HIGH 2 件と MED 2 件 (実質 [4.1] は [1.2] と同一) に対応。 対応した指摘
見送った指摘とその理由
設計判断のポイント[1.1] への対応として「image-only の定期 pull 機能自体を削除」という選択をしました。Codex は「pull 日時を別保存する」「digest 比較する」を提案しましたが:
CI 結果全 5 チェック PASS (Ruff lint / ShellCheck / Python syntax 3.10-3.12) 修正ファイル
|
Codex review [1.1] 対応で削除した「公開イメージの定期再 pull」を、
touch-file 方式で再実装。
実装:
- _pull_marker_path(image): \${DEVBASE_ROOT}/.cache/pulls/<safe-name>
image 名の '/' や ':' を '_' に置換してファイル名安全化
- _pull_age_days(image): touch-file mtime からの経過日数 (None=未存在)
- _mark_pulled(image): pull 成功時に marker を touch
- _ensure_images() の image-only 分岐:
- 不在 → pull → mark
- 前回 pull から N 日経過 → pull → mark
- それ以外 → no-op
メリット:
- JSON parse 不要 (pathlib + time だけ)
- 中断耐性 (壊れた JSON が残らない)
- 手動リセット容易 (rm .cache/pulls/foo で次回再 pull)
- 約 30 行で完結
副次:
- .gitignore に .cache/ を追加
- cli-reference.md に touch-file 仕様を追記
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
追加対応: touch-file ベースで公開イメージの定期 pull を再実装 (commit decf80f)前コミット (23e4e9e) では Codex 指摘 [1.1] への対応として「公開イメージの定期 pull 機能自体を削除」しましたが、ユーザーフィードバックで touch-file 方式なら簡潔に実装できるとの指摘があり、機能を復活させました。 実装方針pull 成功時に touch-file を 追加関数(合計約30行)
|
| Codex 指摘 | 当初対応 | 最終対応 |
|---|---|---|
[1.1] HIGH: Created 依存で pull がループ |
機能削除 | touch-file 方式で再実装 |
| [3.1] MED: build/pull の閾値を 1 つで扱う意味論 | 削除で解消 | 統一閾値のまま (touch-file ベース pull は build と異なる対象だが、ユーザー側からは「7 日経過で更新」という単一 mental model) |
[3.1] については、内部実装は build / pull で別判定 (_get_image_age_days vs _pull_age_days) を行いつつ、ユーザー API (DEVBASE_IMAGE_MAX_AGE_DAYS) は単一閾値のまま維持しています。将来 DEVBASE_BUILD_MAX_AGE_DAYS / DEVBASE_PULL_MAX_AGE_DAYS に分離する余地は残しています。
修正ファイル
lib/devbase/commands/container.py(+57 -10)docs/user/cli-reference.md(+2 -0).gitignore(+1 -0)
[HIGH] 既存 image-only サービスで marker bootstrap PR 適用前から手動 docker pull 済みの公開 image は marker が無く、 _pull_age_days() が永遠に None を返して定期 pull が発火しない不具合。 image-only かつ marker 不在のケースで marker を「now」で bootstrap し、 次回以降 threshold-based pull が正しく作動するよう修正。 option (a) (即 pull) ではなく option (b) (現時点を起点に記録) を選択。 理由: 初回 up での予期せぬネットワーク呼び出しを避け、 最大 7 日の更新遅延 (SLA 厳密ではない) を受容する方が UX として穏便。 [MED] marker filename の衝突を hash で防止 re.sub による単純置換は lossy で、 'a/b:c' と 'a_b/c' がともに 'a_b_c' に衝突する問題があった。 filename を `<sanitized[:60]>--<sha256[:12]>` 形式に変更し、 人間可読性と衝突耐性を両立。 [LOW] 未来 mtime のクランプ 時刻巻き戻しや手動 mtime 操作で marker mtime が未来を指すと、 時刻差が負値になり pull_age < max_age が常に成立して refresh が永続抑止される問題があった。 負値検出時は warning ログを出して 0 を返すよう修正。 動作確認: - collision: a/b:c, a_b/c, a:b/c が全て異なる hash で識別される - bootstrap: marker 無し既存 image で初回 up 時に marker 作成、age=0 - future mtime: 5 日先の mtime → warning + age=0 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex 第二回 review 指摘 対応サマリー (commit eed868d)外部 AI 第二意見 (Codex / gpt-5.4) の再レビューで挙がった HIGH 1 件・MED 1 件・LOW 1 件に対応。 対応した指摘
設計判断: bootstrap 方式Codex は (a) 「marker 無し → 即 pull」を推奨しましたが、本実装では (b) 「marker 無し → 理由:
動作確認見送り
CI 結果全 5 チェック PASS (Ruff lint / ShellCheck / Python syntax 3.10-3.12) 修正ファイル
累計
|
Pull Request
概要
`devbase up` 実行時のイメージ事前チェックを強化し、以下を自動化:
合わせて以下も対応:
関連 Issue
変更点
`lib/devbase/commands/container.py`
`_IMAGE_MAX_AGE_DAYS = 7` を新設
`_ensure_images()` を 4 ケースに拡張:
追加関数:
`_run_build(no_cache: bool = False)`: `bash bin/devbase build --no-cache` を透過
`bin/devbase` (cmd_build の副作用除去)
`--no-cache` 検知時に行っていた `docker builder prune -af` を削除:
ディスククリーンアップが必要な場合は別コマンド(将来 `devbase clean` 等)で明示的に行う方針。
`README.md`
動作確認
やらないこと