refactor(devcontainer): Dockerfile-only + gitignored devcontainer.json for devpod compatibility#687
Conversation
devpod は docker-compose に基づく devcontainer をビルドするとき、基底の docker-compose.yml の build: . の context を正しく継承できず、 .devcontainer/ ディレクトリを context と誤認していた。結果 COPY 命令が entrypoint.sh: not found で失敗する。 VS Code Dev Containers では同じ設定で動作するが、devpod では明示的に context を指定する必要があった。 overlay 側で build.context: . を明示的に設定。compose の relative path 解決 ルールにより . は base compose file の場所 (= repo root) に解決され、 両ツールで同じ build context が使われる。 ローカルで docker compose build を実行して entrypoint.sh が正しく COPY されることを確認済み。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🚀 Preview deployed: https://smalruby.jp/smalruby3-editor/fix/devcontainer-devpod-build-context/ |
devcontainer features (claude-code, github-cli) を devpod の docker-compose ベース devcontainer で使うと、features が生成する Dockerfile-with-features の build context が壊れて COPY entrypoint.sh が \"/entrypoint.sh: not found\" で 失敗する。前段の build context 修正 (commit 8524937) は VS Code 側には 有効だが devpod ではまだ失敗していた。 VS Code Dev Containers では features がそのまま動くため、devpod 固有の ラッパービルド処理に起因するバグと思われる。 回避策として features は使わず、post-create.sh で同等のインストールを行う: - gh CLI: apt 経由で公式リポジトリから install (Debian bookworm 用 GPG 鍵登録) - claude (Claude Code): npm install -g @anthropic-ai/claude-code ローカルでコンテナに入って post-create.sh を実行し、gh 2.92.0 / Claude Code 2.1.138 がインストールされることを確認済み。 副作用: - devcontainer-lock.json は features 用なので不要、削除 - postCreateCommand が初回 build に加えてインストール時間 (約30秒) を消費するが、 キャッシュチェックで再インストールは skip される Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
追加修正: features を使わず post-create.sh でツール installbuild context の明示 (commit 8524937) だけでは devpod の features 経由のラッパービルド で同じエラーが続いていた。devpod は 修正内容 (commit f167e2b)
検証 (main checkout で確認)VS Code Reopen in Container / devpod 両方で動作するはずですが、devpod 側の検証はこの修正適用後に試してください。 |
…onflict 通常 compose (smalruby3-editor-app-1) と devcontainer 用 compose (default-sm-24f22-app-1 など) が同時に host port 8601 を取り合うと、 後発側 (devpod up .) がポート bind に失敗し、container は起動するが network attach に失敗する。結果、container の .NetworkSettings.Networks は 空になり、/etc/resolv.conf も Docker 内部 DNS (127.0.0.11) ではなく外部 forwarder (192.168.65.7) を指してしまい、DNS が一切引けなくなる。 devpod での実機検証で再現: - post-create.sh の curl https://cli.github.com が "Could not resolve host" - docker exec で確認すると getent hosts が何も返さない 恒久対策: docker-compose.devcontainer.yml で ports: !reset [] を指定し、 devcontainer 起動時は host port を一切 bind しないようにする。 IDE 側 (VS Code / devpod) は devcontainer.json の forwardPorts: [8601] を 読んで自分でポート転送するため、compose レベルの host bind は不要。 通常 compose は影響を受けず、従来通り :8601 を公開する。 合わせて README にトラブルシューティングを追記。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
追加修正: host port bind 衝突対応 (devpod 失敗の真因)devpod での実機検証で「 原因通常 compose の ``` 通常 compose container の resolv.confnameserver 127.0.0.11 # ← 内部 DNS あり、解決成功 devpod container の resolv.confnameserver 192.168.65.7 # ← 外部のみ、解決失敗 修正内容 (commit 6977819)`.devcontainer/docker-compose.devcontainer.yml` で host port bind を無効化: ```yaml devcontainer 起動時は host にポートを公開しない。IDE 側 (VS Code / devpod) が `devcontainer.json` の `forwardPorts: [8601]` を読んで自分でポート転送するため問題なし。通常 `docker compose up app` には影響なし。 実機検証修正後、devpod container 内で:
次の検証devpod 環境で再度試してください。既存の壊れた devpod workspace が残っている場合は一度 `devpod delete smalruby3-editor` してから `devpod up .`。 |
devpod 環境では post-create.sh の npm install -g @anthropic-ai/claude-code が
まれに "node: bad option: --max-old-space-size" などのメッセージで exit 1
する事象が起きる。原因は claude の native ELF binary と devpod agent の
組み合わせに起因する Node options 処理の不整合と推測されるが、根本特定は
困難で、手動で再実行すれば成功することは確認済み。
devcontainer up 全体が失敗扱いになると IDE 統合が動かなくなるため、
claude install 失敗は warning に降格して post-create.sh は exit 0 で抜ける。
gh CLI のインストールは引き続き fatal (成功率高い)。
ユーザは container 内で以下を手動実行すれば claude が入る:
npm install -g @anthropic-ai/claude-code
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
追加修正: Claude Code install を non-fatal に発生した現象devpod でビルド成功 → post-create.sh の ``` 切り分け結果
修正 (commit 8d3a206)claude install を非致命に変更。失敗時は warning を出して post-create.sh は exit 0 で抜ける。container 内で手動で `npm install -g @anthropic-ai/claude-code` を実行すれば成功することを確認済み (manual run path で 1 度成功している)。 gh CLI の install は引き続き fatal (成功率高く、ほぼ確実に必要なため)。 検証していただきたいこと
|
…tainer.json
docker-compose ベースの devcontainer は devpod との相性問題があり (build
context 破壊、port 衝突、features 不整合) 安定運用が困難だったため、
Dockerfile-only 構成にリファクタする。
## 主な変更
- .devcontainer/devcontainer.json は .gitignore 対象に変更。
各自で .example をコピーして使う:
cp .devcontainer/devcontainer.json.example .devcontainer/devcontainer.json
- .devcontainer/docker-compose.devcontainer.yml と
docker-compose.local.yml.example は削除 (compose 経由は廃止)
- 通常の docker-compose.yml は無変更。docker compose run app ... は従来通り
- devcontainer features (claude-code, github-cli) を復活。Dockerfile-only なら
devpod でも features が正しく動く
- 既存 compose の named volume (node_modules / .npm / .cache) を devcontainer
でも共有することで、deps の二重インストールを回避。git worktree 切替時の
起動高速化にも寄与
- 個人マウント (~/ghq, ~/.claude*) はテンプレートでコメントアウト状態で提示。
使う人だけアンコメントする
- post-create.sh からツール install ロジックを削除 (features が処理)。
worktree 検出 + setup-worktree 実行のみに簡素化
- 対話的に devcontainer.json を生成するスキルを追加:
.claude/skills/devcontainer-setup/SKILL.md
## 通常開発者への影響
なし。docker compose run --rm app ... は無変更で動く。
本ディレクトリは devpod / VS Code Dev Containers を使いたい人だけが触る。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
大幅リファクタ: docker-compose 撤廃、Dockerfile-only に移行devpod での compose ベース利用が安定しないため、根本方針を変更しました。 変更概要
利用者への影響
追加: 対話的セットアップスキル
動作確認
|
…DISABLE_AUTOUPDATER
container 内 Claude が auto-update すると host の ~/.claude.json まで version
表記が書き換わる問題を回避する。Anthropic 公式 (code.claude.com/docs/en/devcontainer)
の "Avoid mounting host secrets" 原則とも合わせる。
## 変更内容
- containerEnv.DISABLE_AUTOUPDATER=1 を追加 (auto-update 抑止)
- 個人マウントテンプレートから ~/.claude.json bind を削除
(container 内では別途 `claude` でログイン。container fs で永続、
devpod stop/up は跨ぐが rebuild で消える)
- skills/plugins/settings/statusline は ro bind のまま (host で編集、
container は読むだけなので汚染しない)
- memory (~/.claude/projects/-app) は bind rw のまま (host との共有を維持)
- README に新ポリシーを記載
- devcontainer-setup skill の選択肢から auth-only オプションを削除し、
Claude 系を 1 つのまとまりで提示する形に簡略化
## 利用者が初回にやること
container 起動後、初回のみ:
claude
で認証フロー (~/.claude.json は container fs 内に作成、host を汚さない)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
devpod を主体とする日常開発ワークフローのガイドを追加。compose ベースの 旧ワークフローと何が違うか、特に git worktree との組み合わせで何が 変わるかを明示する。 主な内容: - 起動からの 1 日のルーチン (export GH_TOKEN → devpod up → tmux) - compose との挙動差分一覧 - named volume 共有による npm install 二重実行の回避 - worktree ごとに別の devpod workspace (= 別 container) になる点 - 複数 workspace 同時起動の port 衝突 (devpod が auto-assign) - できなくなること (bin/dx の手軽さ、host CDK 認証の container 持ち込み等) - トラブルシューティング (gh / claude / worktree / tmux) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
devpod で
devpod up .を実行したとき以下のエラーで失敗する問題の修正:Root cause
devpod は docker-compose ベースの devcontainer をビルドするとき、基底の
docker-compose.ymlのbuild: .形式の context を正しく継承できず、.devcontainer/配下を build context と誤認する。結果として Dockerfile のCOPY entrypoint.sh /app/entrypoint.shが repo root のentrypoint.shを見つけられず失敗する。VS Code Dev Containers では同じ設定で問題なく動作するが、devpod は明示的に context を指定する必要があった。
Fix
.devcontainer/docker-compose.devcontainer.ymlのappサービスにbuildセクションを明示的に追加:docker compose の relative path 解決ルールでは、
-fで指定された 最初 の compose ファイルの場所からの相対パスとして解釈される。基底 (docker-compose.yml) は repo root にあるため、context: .は repo root に解決される。これにより devpod / VS Code 両方で entrypoint.sh が正しく COPY される。Test plan
docker compose -f docker-compose.yml -f .devcontainer/docker-compose.devcontainer.yml config appを実行し、build.context が<repo root>に解決されることを確認docker compose ... build appを実行し、entrypoint.sh が正しく COPY されてビルドが成功することを確認devpod up .が成功することを確認 (PR 提出者にて実施)