
こんにちは、エブリーでサーバーサイドをメインに担当している清水です。
私のチームではPHP, Laravelを使用して小売店向けのSaaS側Webサービスの開発を行っています。
過去の記事でご紹介した通り、
私たちはモノレポの構成を採用しており、リポジトリの中身は大きく3つに分けることができます。
- モバイルアプリ向け(mobile-api)
- 管理画面向けAPI (dashboard-api)
- 両APIで共通の部分(共通パッケージやGitHub Actionsの設定ファイルなど)
過去に本ブログで紹介されたDev Containersを私たちのチームでも導入検討を行いましたので、本記事でご紹介いたします。
開発環境は Docker を使って整備していたものの、実際の現場では次のような課題を感じていました。
-
新メンバーの環境構築に時間がかかる
ローカルのIDEで使用するPHPのインストール、gitの設定など必要な手順が複数あり、ドキュメントを読んでも初回セットアップで詰まるケースがありました。
※アプリ自体は Docker コンテナ上で動作していたものの、ローカルの IDE(VS Code)で補完や静的解析を有効にするため、ローカルにも PHP をインストールする必要がありました。 -
ローカルを汚したくない
PHP等のプロジェクト固有の開発に必要なものをローカルに直接インストールしたくない、という意見もありました。
PCを変更するときにいろいろインストールし直さなければならなくなる手間が増えることといった問題も起こりえます。 -
VS Code の拡張機能や設定など、開発環境がメンバーによって違う
特に「どの拡張機能を入れるべきか」が明文化されておらず、新規メンバーが最初に迷いやすい状態でした。
「そんな便利な拡張機能あったの!?」みたいなことが起きることもあります。
- 「誰が開いても同じ環境になる」再現性
各メンバーが VS Code で “Reopen in Container” するだけで PHP やその他ツールのバージョン、拡張機能が完全に一致します。 - 環境構築を自動化できる postCreateCommand / postAttachCommand
.env 作成、composer install、DB マイグレーション、GitHub 認証など、手作業になりがちな初期セットアップを自動化できます。
私たちはこれらの作業をmakeコマンドを利用することで部分的に自動化できていましたが、さらに楽できそうです。 - チーム全体で同じ VS Code 拡張をプリセット
Intelephense, Xdebug, Namespace Resolver など、Laravel 開発に必要な拡張を共通化し、環境差異を解消しました。
- postCreateCommand: コンテナが 作成直後またはリビルド直後 に実行されるコマンドを定義する機能
- postAttachCommand: 既存のコンテナに VS Code/Dev Containers が接続(アタッチ)されたときに実行されるコマンドを定義する機能
参考: https://containers.dev/implementors/json_reference/#lifecycle-scripts
devcontainer.jsonに以下のように設定すると起動時の操作を自動化できる
// 初回セットアップ "postCreateCommand": "bash mobile-api/.devcontainer/scripts/postCreateCommand.sh", // 再接続ごとの軽い同期 "postAttachCommand": "bash mobile-api/.devcontainer/scripts/postAttachCommand.sh",
1. モノレポ全体を開発するためのコンテナを新しく作るか、既存のコンテナにDev Containersを入れるか
最初に悩んだのは、「Dev Containers専用のコンテナを新規に構築するか、それとも既存のコンテナを流用するか」でした。
リポジトリはもともと Docker Compose ベースで構築されており、すでにアプリケーションやDBなどの実行環境が整っていました。
そのため、「開発用に新しくコンテナを作り直すのは時間がかかるうえに、既に動いている環境を追加で作成するのも冗長ではないか」という懸念がありました。
まずはお試しとして、既存の mobile-api コンテナに .devcontainer を追加する形 でDev Containers を導入してみることにしました。
2. モノレポ構成ゆえに、コンテナ内から外側を編集できずに困った
既存の mobile-api に .devcontainer を追加して起動してみたところ、思わぬ落とし穴がありました。mobile-api はモノレポの一部のディレクトリであり、その外側には共通パッケージ (packages/common) や GitHub Actions の設定が配置されています。
しかし、Dev Container のマウント対象が mobile-api 直下だけだったため、コンテナ内からリポジトリ外側のファイルを編集できない状況でした。
たとえば、API 側で共通パッケージの修正をしたいときに、コンテナを立ち上げたままでは packages/common にアクセスできず、いったんホスト側で開き直す必要がありました。
モノレポで開発しているからこそ、API側と一緒に共通パッケージを編集したいケースも多いのでかなり悩みました。
最終的には、Dev Container のワークスペースマウントをリポジトリ全体(/workspaces)に変更することで解決しました。
これにより、mobile-api・dashboard-api・packages のすべてをコンテナ内から一貫して操作できるようになりました。
devcontainer.jsonに以下のような内容を追加します
"workspaceFolder": "/workspaces", "mounts": [ "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind,consistency=cached", ],
3. VS CodeのターミナルからGitHubに接続できない
コンテナ内はローカルとは異なる環境なのでGit関連の設定が必要です。
Git操作だけローカルでやればいいのではないか?とも思いましたが、VS Code上の操作ができないことはかなり不便に感じたので対応が必要でした。
devcontainer.json内に git / GitHub CLI のインストール設定を追加
"features": { "ghcr.io/devcontainers/features/git:1": {}, "ghcr.io/devcontainers/features/github-cli:1": {} }
コンテナ内でgh auth loginを叩いてGitHub認証を行う形を採用
- postAttachCommandで以下のコマンドを自動的に実行する形にしました
gh auth login --hostname github.com --git-protocol https --web && gh auth setup-git
- 開き直すたびに認証を求められないように、GitHub CLIの認証情報は名前付きボリュームに保存する形を採用しました
"mounts": [ "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind,consistency=cached", "source=gh_config,target=/root/.config/gh,type=volume" //GitHub用のボリューム ],
- どうしても原因がわからないのですが、自動実行の場合のみ以下のようなエラー表示になるので、手動でブラウザでURLを開いて認証する形で妥協しました
Running the postAttachCommand from devcontainer.json... [devcontainer-postattach] start [devcontainer-postattach] vendor present -> skip install [devcontainer-postattach] gh not logged in -> launching web login ! First copy your one-time code: XXXX-XXXX Press Enter to open https://github.com/login/device in your browser... /usr/bin/xdg-open: 1032: www-browser: not found /usr/bin/xdg-open: 1032: links2: not found /usr/bin/xdg-open: 1032: elinks: not found /usr/bin/xdg-open: 1032: links: not found /usr/bin/xdg-open: 1032: lynx: not found /usr/bin/xdg-open: 1032: w3m: not found xdg-open: no method available for opening 'https://github.com/login/device' ! Failed opening a web browser at https://github.com/login/device exit status 3 Please try entering the URL in your browser manually
{ "name": "mobile-api devcontainer", // ルートの compose.yml を使用 "dockerComposeFile": "../compose.yml", "service": "mobile-api", // モノレポ全体を作業対象に "workspaceFolder": "/workspaces", // 一緒に起動するサービス "runServices": ["mobile-api", "database"], // VS Code 設定 "settings": { "terminal.integrated.defaultProfile.linux": "bash", "git.openRepositoryInParentFolders": "always" }, // 推奨拡張機能 "extensions": [ "bmewburn.vscode-intelephense-client", "xdebug.php-pack", "mehedidracula.php-namespace-resolver", "ms-azuretools.vscode-docker" ], // コンテナ機能(git と GitHub CLI をインストール) "features": { "ghcr.io/devcontainers/features/git:1": {}, "ghcr.io/devcontainers/features/github-cli:1": {} }, // モノレポ全体を /workspaces にマウント // gh CLI の認証情報は volume で永続化 "mounts": [ "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind,consistency=cached", "source=gh_config,target=/root/.config/gh,type=volume" ], // 初回セットアップ "postCreateCommand": "bash mobile-api/.devcontainer/scripts/postCreateCommand.sh", // 再接続ごとの軽い同期 "postAttachCommand": "bash mobile-api/.devcontainer/scripts/postAttachCommand.sh", // コンテナユーザー "remoteUser": "root" }
※部分的にブログ用の内容に書き換えてあります
Dev Containers を導入したことで、VS Code を開いて GitHub の認証を行うだけで、すぐに開発できる環境が整うようになりました。
これまで初期セットアップに時間を取られていた部分が一気に自動化され、特に新メンバーのオンボーディングが大幅に楽になったのではないかと感じています。
まだ本格的な運用段階には入っておらず、今後チーム全体で利用を進めていく中で、思わぬ問題が出てくる可能性もあります。
運用していくうちに「やはり Dev Containers 専用のコンテナを新規に構築した方がよかったかもしれない」と感じる場面が出てくるかもしれない気がしています。
新たに気付くことがあればまた本ブログで紹介したいと思います。
最後までお読みいただきましてありがとうございました。
コメント