Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@
## [Unreleased]

### Added
- **永続化ボリュームをアカウントグループ単位に分離**しました (PLAN39 / #116)。
これまで認証情報と会話ログは全コンテナ共通の `devbase_home_ubuntu` に置かれていたため、
nyle.co.jp で認証した Claude Code / gcloud を kk-generation.com のプロジェクトが
そのまま引き継いでしまい、企業テナントの境界を越えていました。`DEVBASE_ACCOUNT_GROUP`
(未設定なら `default`) で使用する Google / AWS アカウントの単位を宣言すると、
グループごとに `devbase_home_<group>` が作られ `/persistent/group` としてマウントされます。

| 分類 | 置き場 | 内容 |
|---|---|---|
| 共通 | `/persistent/ai` (`devbase_home_ubuntu`) | `~/.claude/plugins` / `skills` / `commands` / `CLAUDE.md` / `settings.json`、`.codex` / `.serena` / `.kiro` / `.ssh` / `share` |
| グループ別 | `/persistent/group` (`devbase_home_<group>`) | `.claude.json`、`~/.claude` 本体 (認証・会話ログ)、`.gemini`、gcloud / gws の設定ディレクトリ |

`~/.claude/plugins` (238MB) のような共通資産はグループ数だけ重複しません。
`default` グループでは初回起動時に既存データを**コピー**してシードするため、
Claude Code の再ログインは発生しません (gcloud / gws はシード元が無いため
全グループで初回 1 回の認証が要ります)。使えないグループ名 (Docker のボリューム名に
できないもの・`ubuntu`・数字だけ) は `devbase up` の前にエラーで弾きます。
詳細は [コンテナ操作ガイド](docs/user/container-operations.md#アカウントグループ) を参照してください。

- **gcloud / gws の設定ディレクトリをアカウントグループ単位に永続化**しました。
`CLOUDSDK_CONFIG` / `GOOGLE_WORKSPACE_CLI_CONFIG_DIR` を `/persistent/group` 配下へ
向けることで、`gcloud auth login` / `gws auth login` のユーザー OAuth が
**コンテナを作り直しても保たれ**、かつグループをまたいで共有されなくなります。
`CLOUDSDK_CONFIG` は gcloud CLI 専用ではなく `google.auth` の探索経路そのものなので、
BigQuery クライアント等も同じ場所を見ます。あわせて `@googleworkspace/cli` (`gws`) を
base イメージへ追加しました (これまでどのコンテナにも入っておらず、設定だけ永続化しても
復旧しませんでした)。

- **`GCP_AUTH_MODE` を新設**しました。`adc` でサービスアカウント鍵を使わず
`gcloud auth application-default login` によるユーザー認証 (ADC) を使い、`key` で
従来どおり鍵を使います。未設定なら鍵の env の有無で自動判定するため、既存プロジェクトは
これまでどおり動きます。`adc` では `GOOGLE_APPLICATION_CREDENTIALS` と `BIGQUERY_KEY_FILE` を
**コンテナへ渡しません** (値だけ残して実体が無いと ADC はユーザー認証へフォールバックせず
`DefaultCredentialsError` で落ちるため)。

> **Warning:** `CLOUDSDK_CONFIG` の導入により、`~/.config/gcloud` は
> **gcloud の設定ディレクトリではなくなりました**。鍵モードで書き出される
> サービスアカウント鍵の置き場でしかなく、コンテナ層 (揮発) に残ります。設定を見たい
> ときは `$CLOUDSDK_CONFIG` を参照してください。

- **`devbase status` に解決されたアカウントグループ**を表示するようにしました。
コンテナの起動ログにも、グループ名と gcloud のアカウントが 1 行出ます。

> **Note:** 上記のうち entrypoint と Dockerfile に関わる変更は、反映に
> `devbase build --no-cache` によるイメージの再ビルドとコンテナの作り直しが要ります。

- **tmux の既定設定 (`/etc/tmux.conf`) を base イメージへ焼き込む**ようにしました。tmux は
起動時に端末の代替画面へ切り替わるため、出力履歴は VS Code のスクロールバックではなく
tmux 自身のバッファに入ります。これまでコンテナの tmux は素の初期状態 (履歴 2000 行・
Expand Down Expand Up @@ -51,6 +97,23 @@
> 再ビルドしていないイメージでは、これまでどおり全フォルダを載せたワークスペースが
> 書き出されます (機能が黙って失われることはありません)。

- **スナップショットの対象が 2 ボリューム**になりました (共通 + アカウントグループ)。
メタデータに対象ボリューム名を記録し、`devbase snapshot list` にも表示します。
分離前に作られた既存スナップショットは**そのまま復元できます**。対象ボリュームの構成が
変わったときは、旧世代へ壊れた差分を積まないよう新しい世代を作ります (旧世代の差分状態
ファイルは別のレイアウトを記録しているため、そこへ差分を積むと差分が壊れます)。
- **`devbase env init` は鍵を登録したときだけ** `GOOGLE_APPLICATION_CREDENTIALS` /
`BIGQUERY_KEY_FILE` を書くようにしました (従来は鍵の有無に関係なく書いていました)。
実体の無いパスが `env` に残っていると ADC がユーザー認証へフォールバックできません。

### Fixed
- entrypoint の symlink 生成で、**入れ子パスの親ディレクトリが作られていなかった**不具合を
直しました。`~/.claude/.credentials.json` は永続領域側の作成が
`No such file or directory` で落ちて壊れた symlink になり、`~/.claude/history.jsonl` は
ファイル判定が `*.json` グロブだったため `.jsonl` にマッチせず**ディレクトリとして**
作られ、Claude Code が追記できませんでした。ファイルとして作るエントリは拡張子ではなく
明示の一覧で判定するようにしています。

- **`plugin.yml` の `requires.devbase` をインストール時に検証**するようにしました。要件を
満たさない Plugin は `devbase plugin install` が中止します。これまでは値を読むだけで
比較しておらず、`project.yml` 形式の Plugin を 2.x へ入れられてしまい、`devbase up` の
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ devbaseは、Docker Composeを使った再現性の高い開発環境を提供
- **豊富なツールセット**: Docker CLI、AWS CLI、gcloud SDK、Terraform、Node.js、AI CLIツールがプリインストール
- **複数コンテナの並行開発**: `devbase project scale`で既存コンテナを再起動せずにスケール可能
- **データ永続化**: 名前付きボリュームでコンテナ再起動後もデータを保持
- **スナップショット管理**: 共通ボリューム `devbase_home_ubuntu`(コンテナ内 `/persistent/ai`。AI 設定・共有ファイル)の増分バックアップ・復元・世代管理
- **アカウントグループ**: 認証情報と会話ログを `DEVBASE_ACCOUNT_GROUP` 単位のボリュームへ分離(共通資産は重複させない)
- **スナップショット管理**: 共通ボリューム `devbase_home_ubuntu`(`/persistent/ai`)とグループボリューム `devbase_home_<group>`(`/persistent/group`)の増分バックアップ・復元・世代管理
- **環境変数の自動収集**: `devbase env init`でAWS/Git/GCP認証情報を対話的に設定
- **階層メニュー TUI**: `devbase list` のプロジェクト一覧(矢印キー移動・名前絞り込み対応)から起動・操作(up / down / login / ps / logs / scale / build / rebuild)を選択。画面最下部の常設メニュー(環境変数 / プラグイン / スナップショット / ステータス)へは ←→ キーで移動できます
- **イメージ再ビルド**: `devbase build [name] --no-cache` でキャッシュ無効の完全再ビルド。`devbase rebuild [name]`(= `build --expires=7`)はイメージが既定 7 日より古いときのみ再ビルドします
Expand Down
19 changes: 19 additions & 0 deletions containers/base/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,24 @@ devbase_setup_gcp_credentials() {
export BIGQUERY_KEY_FILE="$bq_path"
}

# 起動時に「どのグループで、どのアカウントとして動いているか」を 1 行出す。
#
# entrypoint は `set -e` で動くため、未ログインで gcloud が非 0 を返しても起動を
# 落とさないようフォールバックする。gcloud を含まないイメージもあるので存在確認も行う。
devbase_log_account_group() {
local group="${1:-default}"
local account

if command -v gcloud >/dev/null 2>&1; then
account="$(gcloud config get account 2>/dev/null || echo unset)"
[ -n "$account" ] || account="unset"
else
account="gcloud not installed"
fi

echo "Account group: ${group} (gcloud account: ${account}, CLOUDSDK_CONFIG: ${CLOUDSDK_CONFIG:-unset})"
}

# テストは関数定義だけを使う (source 時のみ有効な return で以降を読み飛ばす)。
if [ -n "${DEVBASE_ENTRYPOINT_LIB_ONLY:-}" ]; then
return 0 2>/dev/null || exit 0
Expand Down Expand Up @@ -682,6 +700,7 @@ devbase_setup_ai_settings \
"/home/${USERNAME}" "$AI_PERSISTENT_DIR" "$GROUP_PERSISTENT_DIR" \
"$DEVBASE_ACCOUNT_GROUP" "$USERNAME"
echo "AI agent settings symlinks setup completed"
devbase_log_account_group "$DEVBASE_ACCOUNT_GROUP"
# ========================================

# Repository setup (PLAN32: 1 project = 複数リポジトリ)
Expand Down
14 changes: 9 additions & 5 deletions docs/plugin-dev/compose-yml-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,26 @@ flowchart TB

### 3.1 標準ボリューム

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

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

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

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

### 3.2 Docker Socketのマウント

Expand Down
6 changes: 4 additions & 2 deletions docs/plugin-dev/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,12 @@ flowchart LR

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

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

### 5.4 コンテナイメージの選択
Expand Down
Loading