-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 別ホストの Docker に dev コンテナを立ち上げ、VS Code もそこへ接続する (PLAN52) #164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
1633d26
docs(PLAN52): 実装計画を追加
takemi-ohama b6ea279
feat(project): project.local.yml の docker 節を読む (PLAN52 Task 1)
takemi-ohama 1ad3cae
feat(utils): docker context の解決・確定・反映と gid 取得 (PLAN52 Task 2)
takemi-ohama 5f0c4e3
feat(container): lifecycle コマンドに docker context を通す (PLAN52 Task 3)
takemi-ohama 63de4a3
feat(volume): リモート扱いの生成で bind mount の ~ を docker.home で展開する (PLAN52 T…
takemi-ohama 3a2dfa3
feat(build): shell の build が --context を env exec へ引数で渡し、docker 呼び出しを…
takemi-ohama 6d17565
fix(build): --context を抜いた残りを _DEVBASE_ARGS へ戻し、既存の dispatch 行を保つ
takemi-ohama 9a61d63
feat(editor): 解決した docker context を attach URI の settings.context に載せ…
takemi-ohama 8226b3b
docs: project.local.yml とリモート Docker の使い方を書く (PLAN52 Task 7)
takemi-ohama 3339048
Test: characterize remote Docker context branches and boundaries
takemi-ohama 144399a
Test: characterize remote Docker context runner exceptions and open-i…
takemi-ohama 8c99a22
Refactor: extract_method — 構造改善ラウンド 2 (R2-001..R2-004)
takemi-ohama 9d37270
Refactor: consolidate_duplication — lib/devbase/commands/container.py…
takemi-ohama ff50d5b
Refactor: extract compose phases and consolidate project builds
takemi-ohama 6c541e7
Revert "Refactor: extract compose phases and consolidate project builds"
takemi-ohama 9b9f065
Refactor: consolidate_duplication — lib/devbase/volume/compose.py#_ma…
takemi-ohama bd57f6c
refactor(container): 接続先の確定で project.local.yml を二度読まない
takemi-ohama 739faa3
fix: レビュー指摘を反映 (現在の context の取得を docker_context に一本化・build --context …
takemi-ohama 8d710aa
fix: レビュー指摘を反映 (エディタの推測は docker が実際に使う context に合わせる・長い書式 bind の相対 so…
takemi-ohama 184a012
fix: レビュー指摘を反映 (切替元の機密を切替先 env の読み込み前に落とす・env exec の project.local.ym…
takemi-ohama 0abb782
test: container context のテストで os.environ をテストごとに戻す
takemi-ohama baad328
test: up_harness で context 関連の env とモジュール状態を空にしてから始める
takemi-ohama badeef6
docs(spec): 別ホストの Docker への dev コンテナ起動の確定仕様を残し、PLAN52 を issues/old へ移す
takemi-ohama File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,211 @@ | ||
| # 別ホストの Docker への dev コンテナ起動(docker context) | ||
|
|
||
| ## 概要 | ||
|
|
||
| devbase は、プロジェクトごとの個人設定 `projects/<name>/project.local.yml` に docker context の | ||
| 名前を書くと、そのプロジェクトの `up` / `down` / `ps` / `logs` / `login` / `scale` / `build` / | ||
| `rebuild` を別ホストの docker daemon へ向ける。compose クライアントと機密の復号は手元で行い、 | ||
| daemon だけがリモートにある。リモートに要るのは docker CLI・dockerd・sshd で、devbase・ | ||
| `projects/`・機密鍵をリモートへ複製しない。`devbase up` が開く VS Code は、attach URI の | ||
| `settings.context` でそのホストのコンテナへ接続する。 | ||
|
|
||
| ## 用語 | ||
|
|
||
| | 用語 | 意味 | | ||
| | --- | --- | | ||
| | docker context | docker CLI が daemon への接続先を名前で切り替える仕組み(`docker context ls` の名前) | | ||
| | 現在の context | `DOCKER_CONTEXT` と `DOCKER_HOST` を外した環境で `docker context show` が返す名前 | | ||
| | 解決した context | 優先順位に従って devbase が決めた context 名。未指定なら `None`(従来どおり CLI に委ねる) | | ||
| | リモート扱い | 解決した context が `None` でなく、現在の context と異なる(または現在の context を取得できない)状態 | | ||
| | ローカル扱い | 上記以外。従来と同じ振る舞い | | ||
|
|
||
| ## 構成要素 | ||
|
|
||
| | 要素 | 置き場所 | 責務 | | ||
| | --- | --- | --- | | ||
| | 個人設定の読み込み | `lib/devbase/project/local_config.py` | `project.local.yml` を読み、`docker` 節を検証して `DockerSettings` にする | | ||
| | context の解決・確定・反映 | `lib/devbase/utils/docker_context.py` | `choose_context` / `resolve_target` / `apply` / `reapply` / `reset` / `ensure_remote_gid` / `current_context` / `effective_context` | | ||
| | lifecycle コマンド | `lib/devbase/commands/container.py` | `--context` の受け取り、操作の前後の `reset`、`up` / `scale` での接続先の確定と gid | | ||
| | shell の `build` | `bin/devbase` | `--context` の抜き取りと `env exec --context` 経由の docker 呼び出し | | ||
| | `env exec` | `lib/devbase/commands/env.py` | 子プロセスの環境へ `DOCKER_CONTEXT` を載せる | | ||
| | bind mount の書き換え | `lib/devbase/volume/bind_mounts.py`、`compose.py` | 生成物の `~` を `docker.home` で展開し、書き換えられない mount を警告する | | ||
| | attach URI | `lib/devbase/editor/opener.py` | `settings.context` の決定とフラット URI の提示 | | ||
|
|
||
| ## 仕様 | ||
|
|
||
| ### context の解決 | ||
|
|
||
| 優先順位は **CLI `--context` > 環境変数 `DEVBASE_DOCKER_CONTEXT` > `project.local.yml` の | ||
| `docker.context` > 未指定** である。環境変数の空文字(空白のみを含む)は未指定として扱う。 | ||
| この段階では docker を呼ばない。 | ||
|
|
||
| `--context` は `project` / `container` 配下の `up` / `down` / `ps` / `logs` / `login` / `scale` / | ||
| `build` / `rebuild`、トップレベルのショートカット `up` / `down` / `ps` / `login` / `scale` / | ||
| `build` / `rebuild`、および `env exec` が受け付ける。空文字と空白のみは終了コード 2 で拒む | ||
| (Python の parser と `bin/devbase` の両方)。 | ||
|
|
||
| ### リモート扱いの判定 | ||
|
|
||
| `up` と `scale` は、解決した context を現在の context と比べる。現在の context の問い合わせは | ||
| `DOCKER_CONTEXT` と `DOCKER_HOST` を取り除いた環境で行う。どちらかが残ると docker は | ||
| それぞれ設定先自身・`default` を返し、判定が常に一方へ倒れるためである。 | ||
|
|
||
| | 解決した context | 現在の context との関係 | 扱い | | ||
| | --- | --- | --- | | ||
| | `None` | 問い合わせない | ローカル | | ||
| | 非 `None` | 同じ | ローカル | | ||
| | 非 `None` | 異なる、または取得できない | リモート | | ||
|
|
||
| `docker.home` / `docker.gid` はリモート扱いのときだけ使う。CLI / 環境変数で | ||
| `project.local.yml` の `docker.context` と**別の名前**へ向けたときは、ファイルの `home` / `gid` | ||
| を使わず警告する(別の機材の値を持ち込まない)。 | ||
|
|
||
| ### 環境への反映 | ||
|
|
||
| 解決した context は環境変数 `DOCKER_CONTEXT` として `os.environ` へ載せ、以降の `docker` / | ||
| `docker compose`・`pre-up` / `deploy` フック・`up` からの自動ビルドがすべて継承する。 | ||
| 反映は次の条件を保つ。 | ||
|
|
||
| - context が `None` なら環境を一切触らない | ||
| - `DOCKER_HOST` があれば警告して取り除く。docker は `DOCKER_HOST` を `DOCKER_CONTEXT` より | ||
| 優先するため、残すと context が効かない | ||
| - リモート扱いの `up` / `scale` では `DOCKER_GID` をリモート側の gid に置き換える | ||
| - 反映は冪等で、機密の注入(`_inject_secrets`)の直後に再適用する。機密ストアに | ||
| `DOCKER_CONTEXT` / `DOCKER_GID` / `DOCKER_HOST` があっても確定した接続先が残る | ||
| - 控えは lifecycle 操作の単位で生き、`_dispatch_lifecycle` が開始時と終了時に `reset` して | ||
| 3 変数を元の値へ戻す。1 プロセスで操作を続ける TUI で、前の操作の接続先を持ち越さない | ||
|
|
||
| `name` でプロジェクトを切り替える経路(`project down B` 等)は、切替元の機密を落として | ||
| から切替先の `env` を読み、切替先の機密を注入した後に context を解決する。 | ||
|
|
||
| ### リモート側の gid | ||
|
|
||
| `group_add: ["${DOCKER_GID}"]` に渡す gid は、`docker.gid` の明示 → 控え | ||
| `$DEVBASE_ROOT/.cache/docker-gid/<context>` → `DOCKER_CONTEXT` 付きの | ||
| `docker run --rm -v /var/run/docker.sock:/s alpine:3 stat -c %g /s` の順で決める。取得した値は | ||
| 控えに書く。取得に失敗した(docker が非ゼロ・出力が整数でない)ときは、docker のエラーと | ||
| `docker.gid` の書き方を示して `up` を非ゼロで終える。取得した値が `0` のときは、socket が | ||
| root 所有か rootless Docker の可能性を警告して続行する。控えは自動では消さない。 | ||
|
|
||
| ### bind mount の `~` | ||
|
|
||
| リモート扱いの構成生成では、生成物 `.docker-compose.scale.yml` の全サービスの bind mount で | ||
| `~` と `~/...` を `docker.home` に置き換える。短い書式・長い書式(`type: bind`)の両方に効く。 | ||
| `~user/...` と相対パス(`/` でも `~` でも始まらない source)は書き換えず、一覧で警告する。 | ||
| `docker.home` が無いリモート扱いでは、`~` 系と相対パスの mount を一覧で警告し、`docker.home` | ||
| の指定を促す。ローカル扱いでは書き換えない。 | ||
|
|
||
| ### 自動スナップショット | ||
|
|
||
| リモート扱いの `up` は自動スナップショットを作らず、警告を 1 行出す。`devbase snapshot` 系の | ||
| コマンドと `down` のローテーションは context を解決せず、従来どおり手元を対象にする。 | ||
|
|
||
| ### shell の `build` と `env exec` | ||
|
|
||
| `bin/devbase` の `build)` 分岐は、単体イメージ名の走査より前に `--context NAME` / | ||
| `--context=NAME` を抜き取り、シェル変数に保持する。値は環境変数へ写さず、 | ||
| `compose_with_secrets`(`devbase env exec --context NAME -- ...`)と Python の | ||
| `project build --context NAME` へ引数で渡す。`cmd_build` の `docker buildx build` と | ||
| `docker image inspect` も `compose_with_secrets` を通す。 | ||
|
|
||
| `env exec` はプロジェクト直下(`current_project_name` が決める `projects/<name>`)の | ||
| `project.local.yml` と環境変数、`--context` から context を解決し、機密を載せた**後**の辞書へ | ||
| `DOCKER_CONTEXT` を載せる。`up` からの自動ビルド(`_run_build`)は解決済みの context を | ||
| `bin/devbase build --context <name>` として引数で渡す。 | ||
|
|
||
| ### VS Code の attach URI | ||
|
|
||
| `settings.context` は「`DEVBASE_EDITOR_DOCKER_CONTEXT` の明示 → devbase が解決した context → | ||
| (ssh 先のときだけ)docker が実際に使う context(環境変数を外さない `docker context show`)」の | ||
| 順で決める。解決した context があればローカル端末でもフラット URI に付ける。Remote-SSH 統合 | ||
| 端末でネスト URI と `settings.context` の両方が付くときは、手元の VS Code に同名の context が | ||
| あれば直接 attach できるフラット URI を info で提示する。 | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| participant U as up | ||
| participant R as 解決と確定 | ||
| participant D as docker | ||
| participant C as 構成生成 | ||
| U->>R: 解決(project_dir, --context, environ) | ||
| R->>D: docker context show(DOCKER_CONTEXT / DOCKER_HOST 抜き) | ||
| D-->>R: 現在の context | ||
| R-->>U: DockerTarget | ||
| U->>U: DOCKER_CONTEXT を載せる(DOCKER_HOST は外す) | ||
| alt リモート扱い | ||
| R->>D: docker run alpine stat(控えが無いとき) | ||
| D-->>R: gid | ||
| U->>U: DOCKER_GID を載せる / 自動スナップショットを飛ばす | ||
| end | ||
| U->>C: 生成(scale, secrets, docker_home, remote) | ||
| Note over U,C: 機密注入の直後に反映を再適用 | ||
| U->>D: compose down / up / exec | ||
| U->>U: エディタ(docker_context) | ||
| ``` | ||
|
|
||
| ## データ・設定 | ||
|
|
||
| ### `projects/<name>/project.local.yml` | ||
|
|
||
| git 管理しない。最上位に書けるのは `docker` だけで、他のキーは `ConfigError` になる。 | ||
| `project.yml` に `docker:` を書くと、このファイルへ移す案内付きの `ConfigError` になる。 | ||
| 空ファイルは無いときと同じに扱う。 | ||
|
|
||
| | キー | 型 | 検証 | | ||
| | --- | --- | --- | | ||
| | `docker.context` | 文字列 | 空・空白・制御文字を含むものは拒む | | ||
| | `docker.home` | 文字列 | `/` で始まる絶対パスのみ | | ||
| | `docker.gid` | 整数 | 0 以上。真偽値・文字列は拒む | | ||
|
|
||
| ### `$DEVBASE_ROOT/.cache/docker-gid/<context>` | ||
|
|
||
| 10 進の gid を 1 行で持つ。リモート扱いで gid を取得したときに書き、次回はこれを読む。 | ||
| 整数として読めない内容は無視して取り直す。 | ||
|
|
||
| ### 環境変数 | ||
|
|
||
| | 名前 | 向き | 意味 | | ||
| | --- | --- | --- | | ||
| | `DEVBASE_DOCKER_CONTEXT` | 入力 | context の上書き(グローバル `.env` / プロジェクト `env` / shell)。空文字は未指定 | | ||
| | `DOCKER_CONTEXT` | 出力 | 解決した context。docker CLI と compose が読む | | ||
| | `DOCKER_GID` | 出力 | リモート扱いの `up` / `scale` でだけ上書き | | ||
| | `DOCKER_HOST` | 入力 | context を解決したときは警告して取り除く | | ||
| | `DEVBASE_EDITOR_DOCKER_CONTEXT` | 入力 | attach に使う context を手で決めたいときだけ。解決した context より優先 | | ||
|
|
||
| ## セキュリティ | ||
|
|
||
| `project.local.yml` は接続先の実体(ホスト名・鍵・トークン)を持たず、context の名前だけを | ||
| 持つ。接続先の実体は各マシンの `docker context create` が持つ。age の鍵・`.env`・ | ||
| `project.local.yml` は手元に留まるが、復号済みの機密の値は従来のローカル構成と同じく | ||
| compose の変数展開を通じて接続先の daemon とコンテナへ渡る。接続先は機密を預けてよい | ||
| ホストに限る。 | ||
|
|
||
| ## 運用 | ||
|
|
||
| - 設定が無ければ挙動は変わらない。`project.local.yml` を消せば元に戻る | ||
| - `docker context use` で現在の context 自体をリモートへ向けた状態は補正の対象外 | ||
| - `devbase status` は手元の daemon だけを見る | ||
| - rootless Docker や socket が `root:root` の構成では `docker.gid` を明示する | ||
| - リモート側の gid が変わったら `.cache/docker-gid/<context>` を消すか `docker.gid` を書く | ||
| - イメージはホストごとに別物で、リモート側に無ければリモートでビルドされる | ||
|
|
||
| ## テスト観点 | ||
|
|
||
| - 設定の読み込みと検証(`tests/project/test_local_config.py`)、`project.yml` の `docker:` の拒否 | ||
| - 優先順位・リモート判定・反映・再適用・reset・gid 取得(`tests/utils/test_docker_context.py`) | ||
| - `up` / `scale` / `down` / `ps` / `logs` / `login` の子プロセスに届く `DOCKER_CONTEXT` / | ||
| `DOCKER_GID` / `DOCKER_HOST`、自動スナップショットの回避、TUI とプロジェクト切替での漏れ、 | ||
| 機密注入後の維持、`--context` を受け付ける parser(`tests/commands/test_container_context.py`) | ||
| - `env exec` の `--context` と機密ストアより優先すること、サブディレクトリからの実行 | ||
| (`tests/commands/test_env_exec_context.py`) | ||
| - shell の `build` が `--context` を抜き取り引数で渡すこと、空値の拒否、docker 直接呼び出しの | ||
| 不在(`tests/cli/test_wrapper_build_context.py`) | ||
| - bind mount の展開と警告(`tests/volume/test_bind_mounts.py`、`test_compose_remote_home.py`) | ||
| - attach URI の `settings.context` とフラット URI の提示(`tests/editor/test_opener.py`) | ||
| - 実 daemon への接続(存在しない context のエラー、リモートでのビルドと attach)は手動確認 | ||
|
|
||
| ## 関連リンク | ||
|
|
||
| - [project.yml リファレンス](../user/project-yml.md) | ||
| - [環境変数ガイド「リモート Docker」](../user/environment-variables.md) | ||
| - [CLI リファレンス: project](../user/cli-reference/02-project.md) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.