diff --git a/containers/base/Dockerfile b/containers/base/Dockerfile index 80757f78..6f78c656 100644 --- a/containers/base/Dockerfile +++ b/containers/base/Dockerfile @@ -201,6 +201,7 @@ RUN set -eux; \ # AI CLI の起動定義。~/.bashrc へ直接書かずファイルにしているのは、Docker を # 起動せずに tests/containers/test_ai_cli_aliases.py で振る舞いを固定するため。 +RUN sudo install -d -m 0755 /etc/devbase COPY --chmod=0644 ai-cli-aliases.sh /etc/devbase/ai-cli-aliases.sh RUN set -eux; \ diff --git a/docs/specifications/ai-cli-alias-loading.md b/docs/specifications/ai-cli-alias-loading.md new file mode 100644 index 00000000..6b9643e1 --- /dev/null +++ b/docs/specifications/ai-cli-alias-loading.md @@ -0,0 +1,40 @@ +# AI CLI alias の読み込み + +## 概要 + +base イメージは、AI CLI の起動 alias を `/etc/devbase/ai-cli-aliases.sh` に配置し、一般ユーザーの +Bash 初期化時に読み込める状態を提供する。 + +## 仕様 + +`/etc/devbase` は root 所有、permission `0755` で明示的に作成する。その後、 +`ai-cli-aliases.sh` を root 所有、permission `0644` で配置する。 + +Dockerfile では一般ユーザーへ切り替えた後にこの設定を行うため、ディレクトリ作成には +`sudo install -d -m 0755 /etc/devbase` を使用する。ファイル用の `COPY --chmod=0644` に親 +ディレクトリの暗黙作成を任せると、親も `0644` になって一般ユーザーが配下を探索できないため、 +ディレクトリ作成は必ず `COPY` より先に行う。 + +常に次の条件を保つ。 + +- `/etc/devbase` は全ユーザーが探索できる `0755` とする。 +- `/etc/devbase/ai-cli-aliases.sh` は全ユーザーが読み取れる `0644` とする。 +- 一般ユーザーは alias ファイルを source できる。 +- alias の内容と起動オプションは、ディレクトリ permission の設定から独立させる。 + +## 運用 + +設定変更は base イメージの再ビルドとコンテナの再作成後に反映される。既存コンテナで +`/etc/devbase` が `0644` の場合は root で `chmod 0755 /etc/devbase` を実行すれば一時復旧できるが、 +恒久対応には修正済みイメージを使用する。 + +## テスト観点 + +- Dockerfile が `/etc/devbase` を `0755` で作成してから alias ファイルを配置すること。 +- ビルドしたイメージで `/etc/devbase` が `0755`、alias ファイルが `0644` になること。 +- `ubuntu` ユーザーが `/etc/devbase/ai-cli-aliases.sh` を source できること。 +- 既存の AI CLI alias 定義と起動オプションが変わらないこと。 + +## 関連リンク + +- [Issue #156](https://github.com/devbasex/devbase/issues/156) diff --git a/tests/containers/test_ai_cli_aliases.py b/tests/containers/test_ai_cli_aliases.py index 4432172c..b9490147 100644 --- a/tests/containers/test_ai_cli_aliases.py +++ b/tests/containers/test_ai_cli_aliases.py @@ -21,6 +21,7 @@ import pytest ALIASES = Path(__file__).resolve().parents[2] / "containers" / "base" / "ai-cli-aliases.sh" +DOCKERFILE = ALIASES.with_name("Dockerfile") def _statements() -> str: @@ -34,6 +35,22 @@ def _statements() -> str: if line.strip() and not line.lstrip().startswith("#") ) + +def test_dockerfile_creates_readable_alias_directory_before_copy(): + """親ディレクトリは全ユーザーが探索できる ``0755`` で先に作る。 + + BuildKit は未作成の親ディレクトリを ``COPY --chmod`` と同じ mode で作るため、 + ファイル用の ``0644`` だけを指定すると ``/etc/devbase`` も ``0644`` になり、 + ubuntu ユーザーが配下を source できない。 + """ + dockerfile = DOCKERFILE.read_text() + mkdir = "RUN sudo install -d -m 0755 /etc/devbase" + copy = "COPY --chmod=0644 ai-cli-aliases.sh /etc/devbase/ai-cli-aliases.sh" + + assert mkdir in dockerfile + assert copy in dockerfile + assert dockerfile.index(mkdir) < dockerfile.index(copy) + #: 定義名 -> (実体, 固定オプション) LAUNCHERS = { "claude": ("claude", ["--dangerously-skip-permissions"]),