Skip to content

Commit c5cd22d

Browse files
takemi-ohamaclaude
andauthored
feat(snapshot,status): スナップショットのグループ対応と可視化・ドキュメント (PLAN39 PR4) (#126)
スナップショットの対象を「共通 + アカウントグループ」の 2 本にし、いま自分が どのグループにいるのかを status と起動ログで分かるようにする。 - snapshot — 対象ボリュームを固定値から 2 本へ。1 つのアーカイブにまとめるため コンテナ内では /source/ai と /source/group に並べてマウントする。メタデータへ 対象ボリューム名を記録し、`devbase snapshot list` にも表示する - 旧スナップショット (volume: devbase_home_ubuntu のみ) は共通ボリュームを ルートへ直接マウントする旧レイアウトとして**そのまま復元できる** - 対象ボリュームの構成が変わったら新しい世代を作る。旧世代の snar は別の レイアウトを記録しており、そこへ差分を積むと全ファイルが移動したものとして 扱われて差分が壊れるため。明示的に古い世代を指定された場合は理由を出して止める - 復元時のクリアはマウントポイント自身ではなく**各マウントの直下**を消す (busy) - `devbase status` の [環境] にアカウントグループとボリューム名を出す。グループ名が 不正でも例外にせず表示に留める (status は状態を見るコマンドで、設定の誤りで 一覧全体を出せなくする必要はない) - entrypoint の起動ログにグループと gcloud のアカウントを 1 行出す。未ログインや gcloud 不在で `set -e` の起動を落とさないようフォールバックする - ドキュメント — ボリューム構造の表、アカウントグループの説明、2 層の永続化、 初回シード、スナップショットの対象と世代分割、README / CHANGELOG Claude-Session: https://claude.ai/code/session_01S5oA2PqY6UX2Ca3t78886t Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent a38a542 commit c5cd22d

15 files changed

Lines changed: 860 additions & 49 deletions

‎CHANGELOG.md‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,52 @@
55
## [Unreleased]
66

77
### Added
8+
- **永続化ボリュームをアカウントグループ単位に分離**しました (PLAN39 / #116)。
9+
これまで認証情報と会話ログは全コンテナ共通の `devbase_home_ubuntu` に置かれていたため、
10+
nyle.co.jp で認証した Claude Code / gcloud を kk-generation.com のプロジェクトが
11+
そのまま引き継いでしまい、企業テナントの境界を越えていました。`DEVBASE_ACCOUNT_GROUP`
12+
(未設定なら `default`) で使用する Google / AWS アカウントの単位を宣言すると、
13+
グループごとに `devbase_home_<group>` が作られ `/persistent/group` としてマウントされます。
14+
15+
| 分類 | 置き場 | 内容 |
16+
|---|---|---|
17+
| 共通 | `/persistent/ai` (`devbase_home_ubuntu`) | `~/.claude/plugins` / `skills` / `commands` / `CLAUDE.md` / `settings.json`、`.codex` / `.serena` / `.kiro` / `.ssh` / `share` |
18+
| グループ別 | `/persistent/group` (`devbase_home_<group>`) | `.claude.json`、`~/.claude` 本体 (認証・会話ログ)、`.gemini`、gcloud / gws の設定ディレクトリ |
19+
20+
`~/.claude/plugins` (238MB) のような共通資産はグループ数だけ重複しません。
21+
`default` グループでは初回起動時に既存データを**コピー**してシードするため、
22+
Claude Code の再ログインは発生しません (gcloud / gws はシード元が無いため
23+
全グループで初回 1 回の認証が要ります)。使えないグループ名 (Docker のボリューム名に
24+
できないもの・`ubuntu`・数字だけ) は `devbase up` の前にエラーで弾きます。
25+
詳細は [コンテナ操作ガイド](docs/user/container-operations.md#アカウントグループ) を参照してください。
26+
27+
- **gcloud / gws の設定ディレクトリをアカウントグループ単位に永続化**しました。
28+
`CLOUDSDK_CONFIG` / `GOOGLE_WORKSPACE_CLI_CONFIG_DIR` を `/persistent/group` 配下へ
29+
向けることで、`gcloud auth login` / `gws auth login` のユーザー OAuth が
30+
**コンテナを作り直しても保たれ**、かつグループをまたいで共有されなくなります。
31+
`CLOUDSDK_CONFIG` は gcloud CLI 専用ではなく `google.auth` の探索経路そのものなので、
32+
BigQuery クライアント等も同じ場所を見ます。あわせて `@googleworkspace/cli` (`gws`) を
33+
base イメージへ追加しました (これまでどのコンテナにも入っておらず、設定だけ永続化しても
34+
復旧しませんでした)。
35+
36+
- **`GCP_AUTH_MODE` を新設**しました。`adc` でサービスアカウント鍵を使わず
37+
`gcloud auth application-default login` によるユーザー認証 (ADC) を使い、`key` で
38+
従来どおり鍵を使います。未設定なら鍵の env の有無で自動判定するため、既存プロジェクトは
39+
これまでどおり動きます。`adc` では `GOOGLE_APPLICATION_CREDENTIALS` と `BIGQUERY_KEY_FILE` を
40+
**コンテナへ渡しません** (値だけ残して実体が無いと ADC はユーザー認証へフォールバックせず
41+
`DefaultCredentialsError` で落ちるため)。
42+
43+
> **Warning:** `CLOUDSDK_CONFIG` の導入により、`~/.config/gcloud` は
44+
> **gcloud の設定ディレクトリではなくなりました**。鍵モードで書き出される
45+
> サービスアカウント鍵の置き場でしかなく、コンテナ層 (揮発) に残ります。設定を見たい
46+
> ときは `$CLOUDSDK_CONFIG` を参照してください。
47+
48+
- **`devbase status` に解決されたアカウントグループ**を表示するようにしました。
49+
コンテナの起動ログにも、グループ名と gcloud のアカウントが 1 行出ます。
50+
51+
> **Note:** 上記のうち entrypoint と Dockerfile に関わる変更は、反映に
52+
> `devbase build --no-cache` によるイメージの再ビルドとコンテナの作り直しが要ります。
53+
854
- **tmux の既定設定 (`/etc/tmux.conf`) を base イメージへ焼き込む**ようにしました。tmux は
955
起動時に端末の代替画面へ切り替わるため、出力履歴は VS Code のスクロールバックではなく
1056
tmux 自身のバッファに入ります。これまでコンテナの tmux は素の初期状態 (履歴 2000 行・
@@ -51,6 +97,23 @@
5197
> 再ビルドしていないイメージでは、これまでどおり全フォルダを載せたワークスペースが
5298
> 書き出されます (機能が黙って失われることはありません)。
5399
100+
- **スナップショットの対象が 2 ボリューム**になりました (共通 + アカウントグループ)。
101+
メタデータに対象ボリューム名を記録し、`devbase snapshot list` にも表示します。
102+
分離前に作られた既存スナップショットは**そのまま復元できます**。対象ボリュームの構成が
103+
変わったときは、旧世代へ壊れた差分を積まないよう新しい世代を作ります (旧世代の差分状態
104+
ファイルは別のレイアウトを記録しているため、そこへ差分を積むと差分が壊れます)。
105+
- **`devbase env init` は鍵を登録したときだけ** `GOOGLE_APPLICATION_CREDENTIALS` /
106+
`BIGQUERY_KEY_FILE` を書くようにしました (従来は鍵の有無に関係なく書いていました)。
107+
実体の無いパスが `env` に残っていると ADC がユーザー認証へフォールバックできません。
108+
109+
### Fixed
110+
- entrypoint の symlink 生成で、**入れ子パスの親ディレクトリが作られていなかった**不具合を
111+
直しました。`~/.claude/.credentials.json` は永続領域側の作成が
112+
`No such file or directory` で落ちて壊れた symlink になり、`~/.claude/history.jsonl` は
113+
ファイル判定が `*.json` グロブだったため `.jsonl` にマッチせず**ディレクトリとして**
114+
作られ、Claude Code が追記できませんでした。ファイルとして作るエントリは拡張子ではなく
115+
明示の一覧で判定するようにしています。
116+
54117
- **`plugin.yml` の `requires.devbase` をインストール時に検証**するようにしました。要件を
55118
満たさない Plugin は `devbase plugin install` が中止します。これまでは値を読むだけで
56119
比較しておらず、`project.yml` 形式の Plugin を 2.x へ入れられてしまい、`devbase up` の

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ devbaseは、Docker Composeを使った再現性の高い開発環境を提供
1313
- **豊富なツールセット**: Docker CLI、AWS CLI、gcloud SDK、Terraform、Node.js、AI CLIツールがプリインストール
1414
- **複数コンテナの並行開発**: `devbase project scale`で既存コンテナを再起動せずにスケール可能
1515
- **データ永続化**: 名前付きボリュームでコンテナ再起動後もデータを保持
16-
- **スナップショット管理**: 共通ボリューム `devbase_home_ubuntu`(コンテナ内 `/persistent/ai`。AI 設定・共有ファイル)の増分バックアップ・復元・世代管理
16+
- **アカウントグループ**: 認証情報と会話ログを `DEVBASE_ACCOUNT_GROUP` 単位のボリュームへ分離(共通資産は重複させない)
17+
- **スナップショット管理**: 共通ボリューム `devbase_home_ubuntu`(`/persistent/ai`)とグループボリューム `devbase_home_<group>`(`/persistent/group`)の増分バックアップ・復元・世代管理
1718
- **環境変数の自動収集**: `devbase env init`でAWS/Git/GCP認証情報を対話的に設定
1819
- **階層メニュー TUI**: `devbase list` のプロジェクト一覧(矢印キー移動・名前絞り込み対応)から起動・操作(up / down / login / ps / logs / scale / build / rebuild)を選択。画面最下部の常設メニュー(環境変数 / プラグイン / スナップショット / ステータス)へは ←→ キーで移動できます
1920
- **イメージ再ビルド**: `devbase build [name] --no-cache` でキャッシュ無効の完全再ビルド。`devbase rebuild [name]`(= `build --expires=7`)はイメージが既定 7 日より古いときのみ再ビルドします

‎containers/base/entrypoint.sh‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,24 @@ devbase_setup_gcp_credentials() {
496496
export BIGQUERY_KEY_FILE="$bq_path"
497497
}
498498

499+
# 起動時に「どのグループで、どのアカウントとして動いているか」を 1 行出す。
500+
#
501+
# entrypoint は `set -e` で動くため、未ログインで gcloud が非 0 を返しても起動を
502+
# 落とさないようフォールバックする。gcloud を含まないイメージもあるので存在確認も行う。
503+
devbase_log_account_group() {
504+
local group="${1:-default}"
505+
local account
506+
507+
if command -v gcloud >/dev/null 2>&1; then
508+
account="$(gcloud config get account 2>/dev/null || echo unset)"
509+
[ -n "$account" ] || account="unset"
510+
else
511+
account="gcloud not installed"
512+
fi
513+
514+
echo "Account group: ${group} (gcloud account: ${account}, CLOUDSDK_CONFIG: ${CLOUDSDK_CONFIG:-unset})"
515+
}
516+
499517
# テストは関数定義だけを使う (source 時のみ有効な return で以降を読み飛ばす)。
500518
if [ -n "${DEVBASE_ENTRYPOINT_LIB_ONLY:-}" ]; then
501519
return 0 2>/dev/null || exit 0
@@ -682,6 +700,7 @@ devbase_setup_ai_settings \
682700
"/home/${USERNAME}" "$AI_PERSISTENT_DIR" "$GROUP_PERSISTENT_DIR" \
683701
"$DEVBASE_ACCOUNT_GROUP" "$USERNAME"
684702
echo "AI agent settings symlinks setup completed"
703+
devbase_log_account_group "$DEVBASE_ACCOUNT_GROUP"
685704
# ========================================
686705

687706
# Repository setup (PLAN32: 1 project = 複数リポジトリ)

‎docs/plugin-dev/compose-yml-guidelines.md‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,26 @@ flowchart TB
9898

9999
### 3.1 標準ボリューム
100100

101-
devbaseでは2種類のボリュームパターンを使い分けます。
101+
devbaseでは3種類のボリュームパターンを使い分けます。
102102

103103
```yaml
104104
volumes:
105-
- devbase_home_ubuntu:/persistent/ai # 全コンテナ共有(AI設定)
105+
- devbase_home_ubuntu:/persistent/ai # 全コンテナ共有(共通AI資産)
106+
- devbase_home_default:/persistent/group # アカウントグループ単位(認証・履歴)
106107
- ${COMPOSE_PROJECT_NAME}_work_${CONTAINER_INDEX:-1}:/work # コンテナ専用
107108
```
108109

109110
| ボリューム | マウント先 | 共有範囲 | 用途 |
110111
|-----------|-----------|----------|------|
111-
| `devbase_home_ubuntu` | `/persistent/ai` | 全コンテナ | AI CLI 設定(`.claude` 等)、SSH鍵、共有ファイル置き場(`share`)。`~/.claude` 等は entrypoint が symlink |
112+
| `devbase_home_ubuntu` | `/persistent/ai` | 全コンテナ | 契約に紐づかない共通資産(`~/.claude/plugins` 等)、SSH鍵、共有ファイル置き場(`share`)。entrypoint が symlink |
113+
| `devbase_home_<group>` | `/persistent/group` | 同じアカウントグループのコンテナ | 認証情報と会話ログ(`~/.claude` 本体、`.gemini`、gcloud / gws の設定) |
112114
| `${COMPOSE_PROJECT_NAME}_work_${CONTAINER_INDEX:-1}` | `/work` | コンテナ専用 | ソースコード、ビルド成果物 |
113115

114-
> **Note:** マウント先は **`/persistent/ai`** です(旧 `/home/ubuntu` 直接マウントは廃止)。
116+
> **Note:** マウント先は **`/persistent/ai`** と **`/persistent/group`** です(旧 `/home/ubuntu` 直接マウントは廃止)。
115117
> これらの標準ボリュームは compose.yml に明記しなくても devbase がスケール用 compose 生成時に
116-
> 自動注入します。明記する場合も必ず `/persistent/ai` を使ってください。
118+
> 自動注入します。**グループボリュームの名前は `DEVBASE_ACCOUNT_GROUP` から devbase が決める**ので、
119+
> プロジェクト側で書く必要はありません(書いた場合も生成時に正しい名前へ差し替えられます)。
120+
> 明記する場合も必ず `/persistent/ai` / `/persistent/group` を使ってください。
117121

118122
### 3.2 Docker Socketのマウント
119123

‎docs/plugin-dev/quickstart.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,12 @@ flowchart LR
318318

319319
| 用途 | ボリューム名パターン | マウント先 | 共有範囲 |
320320
|------|---------------------|-----------|----------|
321-
| AI 設定・共有ファイル | `devbase_home_ubuntu` | `/persistent/ai` | 全コンテナ共有 |
321+
| 共通 AI 資産・共有ファイル | `devbase_home_ubuntu` | `/persistent/ai` | 全コンテナ共有 |
322+
| 認証・会話ログ | `devbase_home_<group>` | `/persistent/group` | 同じアカウントグループ |
322323
| 作業ディレクトリ | `${COMPOSE_PROJECT_NAME}_work_${CONTAINER_INDEX:-1}` | `/work` | コンテナ専用 |
323324

324-
- `devbase_home_ubuntu`(`/persistent/ai`)は AI CLI 設定・SSH 鍵・共有ファイルなど、コンテナ横断で共有したい設定の永続化に使用(`~/.claude` 等は entrypoint が symlink。旧 `/home/ubuntu` 直接マウントは廃止)
325+
- `devbase_home_ubuntu`(`/persistent/ai`)は SSH 鍵・共有ファイル・`~/.claude/plugins` など、契約に紐づかずコンテナ横断で共有したい資産の永続化に使用(entrypoint が symlink。旧 `/home/ubuntu` 直接マウントは廃止)
326+
- `devbase_home_<group>`(`/persistent/group`)は認証情報と会話ログ。`<group>` は `DEVBASE_ACCOUNT_GROUP`(未設定なら `default`)で決まり、devbase が生成 compose へ自動注入する
325327
- 作業ディレクトリボリュームはプロジェクトごと・コンテナインデックスごとに独立
326328

327329
### 5.4 コンテナイメージの選択

0 commit comments

Comments
 (0)