何を見つけたか
プロジェクトの env で共通機密のキーを空上書きしても、コンテナへは共通機密の値が入ることがあります。稼働中の with-ai-dev コンテナで確認しました。
$ docker exec with-ai-dev-dev-1 bash -lc 'echo "$GOOGLE_CLOUD_PROJECT / $GCP_ACTIVE_PROFILE / $DEVBASE_ACCOUNT_GROUP"'
nyle-carmo-analysis / default / with
projects/with-ai-dev/env は次のとおりで、期待値は GOOGLE_CLOUD_PROJECT が空、GCP_ACTIVE_PROFILE が with です。
DEVBASE_ACCOUNT_GROUP=with
GCP_ACTIVE_PROFILE=with
GOOGLE_CLOUD_PROJECT=
3 つのうち DEVBASE_ACCOUNT_GROUP だけが期待どおりです。 この非対称が手がかりになります。生成された .docker-compose.scale.yml を見ると、扱いが 2 通りに分かれています。
environment:
- GCP_ACTIVE_PROFILE # 名前だけ。値は docker compose 実行時の環境から取る
- GOOGLE_CLOUD_PROJECT # 同上
- DEVBASE_ACCOUNT_GROUP=with # 値がリテラルで書かれている
名前だけの受け渡しは env_file: より優先されるため、env_file に書いた空上書きは負けます。値は _inject_secrets が docker compose の実行前に環境へ載せたものになります。
タイミング
古いコンテナが残っているだけ、という筋は成り立ちません。
| 出来事 |
時刻 |
env へ空上書きを入れたコミット(devbase-ext bddbe18) |
2026-09-01 11:49 UTC |
.docker-compose.scale.yml の生成 |
2026-09-02 00:54:28 UTC |
| コンテナの起動 |
2026-09-02 00:54:29 UTC |
生成の時点で env は 13 時間前から現在の内容でした。実際、生成器は DEVBASE_ACCOUNT_GROUP=with を読み取って compose へ書き込んでいます。
どこで見つけたか
lib/devbase/env/runtime.py の _project_env_overrides()(114-135 行)。
keys = EnvFile.parse_bytes(raw).keys()
return {key: os.environ[key] for key in keys if key in os.environ}
値をファイルから読まず os.environ から取ります。 コメントのとおり、env 内の変数参照(APP_ROOT=$APP_HOME/app)を展開済みの値で拾うための設計です。裏を返すと、起動ラッパーが対象プロジェクトの env を os.environ へ載せていない経路では、この上書きが 1 件も効きません。
手元で対象ディレクトリの env を source してから runtime.resolve() を呼ぶと、期待どおりに解決されます。
[with-ai-dev]
GOOGLE_CLOUD_PROJECT = []
GCP_ACTIVE_PROFILE = [with]
つまり実装は「env が os.environ に載っていれば正しい」状態で、載せる側の経路のどれかが抜けていると読めます。EnvFile.parse_bytes はキーを正しく拾えており(10 キーすべて取得を確認)、パース側の問題ではありません。
当時どのディレクトリからどう devbase up を実行したかは記録に残っておらず、再現手順を確立できていません。 そのため「どの経路が抜けているか」は未特定です。
なぜこの変更の範囲外なのか
PLAN50(gemini の Vertex AI 強制をやめる)の受け入れ条件は起動定義の振る舞いで、機密の解決経路は対象外です。issues/PLAN50_gemini-vertex-alias.md の「対象範囲(含まない)」に明記しています。
直さないと何が起きるか
プロジェクトの env による共通機密の打ち消しが、経路によって効いたり効かなかったりします。失敗しても何も表示されません。
with-ai-dev の例では、withjp のアカウントで認証したコンテナに nyle の GCP プロジェクト ID が入り、gemini が Vertex AI を叩いて失敗していました。企業をまたいで設定が混ざる形なので、気づきにくいわりに影響が大きいところです。
同じ形の打ち消しは project-trygroup-prd でも使っており、v3.2.0 で追加した GOOGLE_GENAI_USE_VERTEXAI= の打ち消しも同じ仕組みに乗っています。
切り分けの候補:
devbase up <name> / devbase up(プロジェクト内) / devbase project up <name> のそれぞれで、os.environ に対象プロジェクトの env が載っているかを確かめる
- 載っていない経路があれば、
_project_env_overrides がファイル側の値へ落ちる(ただし変数展開の扱いを決める必要がある)か、ラッパー側で必ず載せる
- 稼働中の
with-ai-dev-dev-1 コンテナに現象が残っているので、作り直す前に採取する
由来
issue #139 の作業から派生(PLAN50 / PR #149)
進行
モード: operation / 計画: issues/PLAN53_openbao-switchover.md
何を見つけたか
プロジェクトの
envで共通機密のキーを空上書きしても、コンテナへは共通機密の値が入ることがあります。稼働中のwith-ai-devコンテナで確認しました。projects/with-ai-dev/envは次のとおりで、期待値はGOOGLE_CLOUD_PROJECTが空、GCP_ACTIVE_PROFILEがwithです。3 つのうち
DEVBASE_ACCOUNT_GROUPだけが期待どおりです。 この非対称が手がかりになります。生成された.docker-compose.scale.ymlを見ると、扱いが 2 通りに分かれています。名前だけの受け渡しは
env_file:より優先されるため、env_fileに書いた空上書きは負けます。値は_inject_secretsがdocker composeの実行前に環境へ載せたものになります。タイミング
古いコンテナが残っているだけ、という筋は成り立ちません。
envへ空上書きを入れたコミット(devbase-extbddbe18).docker-compose.scale.ymlの生成生成の時点で
envは 13 時間前から現在の内容でした。実際、生成器はDEVBASE_ACCOUNT_GROUP=withを読み取って compose へ書き込んでいます。どこで見つけたか
lib/devbase/env/runtime.pyの_project_env_overrides()(114-135 行)。値をファイルから読まず
os.environから取ります。 コメントのとおり、env内の変数参照(APP_ROOT=$APP_HOME/app)を展開済みの値で拾うための設計です。裏を返すと、起動ラッパーが対象プロジェクトのenvをos.environへ載せていない経路では、この上書きが 1 件も効きません。手元で対象ディレクトリの
envをsourceしてからruntime.resolve()を呼ぶと、期待どおりに解決されます。つまり実装は「
envがos.environに載っていれば正しい」状態で、載せる側の経路のどれかが抜けていると読めます。EnvFile.parse_bytesはキーを正しく拾えており(10 キーすべて取得を確認)、パース側の問題ではありません。当時どのディレクトリからどう
devbase upを実行したかは記録に残っておらず、再現手順を確立できていません。 そのため「どの経路が抜けているか」は未特定です。なぜこの変更の範囲外なのか
PLAN50(
geminiの Vertex AI 強制をやめる)の受け入れ条件は起動定義の振る舞いで、機密の解決経路は対象外です。issues/PLAN50_gemini-vertex-alias.mdの「対象範囲(含まない)」に明記しています。直さないと何が起きるか
プロジェクトの
envによる共通機密の打ち消しが、経路によって効いたり効かなかったりします。失敗しても何も表示されません。with-ai-devの例では、withjp のアカウントで認証したコンテナに nyle の GCP プロジェクト ID が入り、gemini が Vertex AI を叩いて失敗していました。企業をまたいで設定が混ざる形なので、気づきにくいわりに影響が大きいところです。同じ形の打ち消しは
project-trygroup-prdでも使っており、v3.2.0 で追加したGOOGLE_GENAI_USE_VERTEXAI=の打ち消しも同じ仕組みに乗っています。切り分けの候補:
devbase up <name>/devbase up(プロジェクト内) /devbase project up <name>のそれぞれで、os.environに対象プロジェクトのenvが載っているかを確かめる_project_env_overridesがファイル側の値へ落ちる(ただし変数展開の扱いを決める必要がある)か、ラッパー側で必ず載せるwith-ai-dev-dev-1コンテナに現象が残っているので、作り直す前に採取する由来
issue #139 の作業から派生(PLAN50 / PR #149)
進行
モード: operation / 計画:
issues/PLAN53_openbao-switchover.md