DockerやDocker Composeの登場により、アプリケーションの実行環境はポータブルになり、開発者間で同じ環境を共有することが容易になりました。
しかし、多くの開発現場では、開発環境に関して、未だに以下のような課題が残されています。
- 環境構築の手順が多くて時間がかかる
- オンボーディングがスムーズに進まない
- 人によって上手く動かない場合がある
- 「Macだと動くけどWindowsだと動かない」「Intel Macだと動くけどM1 Macだと動かない」など
- プロジェクトとごとに必要なパッケージやVSCodeの拡張が異なり、切り替えが面倒。競合して動かない場合も。。
- ローカル環境の汚染。何を入れたか覚えていない
- PCを新調・初期化する度にゼロから環境構築が必要
今回は、こういった環境構築に関する問題を解消するための、「Dev Container」および「GitHub Codespaces」というソリューションをご紹介します。
少しでもより良い開発環境の構築をするための参考になれば幸いです。
Dev Containerとは?
Dev Containerとは、Visual Studio Code(VSCode)の拡張機能で、Dockerコンテナ上にVSCodeの開発環境を構築できる仕組みのことです。
参考: Developing inside a Container
これまでは、それぞれのPC(MacやWindows)にインストールしたVSCode上で、アプリケーションの実行環境としてのDockerを動かしていました。
しかし、Dev Containerでは、VSCode上でコンテナ化されたVSCodeを起動し、その上でアプリケーションのDockerコンテナを動かします。
この仕組みを使うことで、開発者は、あるプロジェクトを開いたときに、Dev Containerを起動をするだけで開発環境を用意することができます。
自分のPCに様々なパッケージをインストールしたり、VSCodeの拡張をインストールする必要はありません。
つまり、それぞれのPCとは完全に隔離した環境でVSCodeを起動し開発することができるのです。
GitHub Codespacesとは?
GitHub Codespacesとは、GitHubが提供するブラウザベースの統合開発環境(IDE)です。
GitHubがホストするクラウド上の仮想マシン(Azure上のVM)で、VSCodeのような開発環境を提供します。
クラウド上で動作しているため、開発者はデバイスや場所に依存せず、どこからでもコードの編集や実行が可能になります。
また、個人のPCスペックに依存しないため、非常に高速に動作するのも特徴です。
Dev Container on GitHub Codespaces
先ほどVSCode上でDev Containerを起動するという話をしましたが、実はGitHub Codespaces上でもDev Containerを起動させることができます。
これにより、自身のPCの環境やスペックに依存することのない開発環境を柔軟な構成で構築することができます。
Dev ContainerとRemote ContainerとRemote Developmentの違いについて
ネット上ではDev ContainerとRemote ContainerとRemote Developmentを混同している記事をよく見かけます。
それぞれを適切に区別するために、ここで整理しておきます。
Dev Container
Dev Containerは先ほど紹介したので説明不要でしょう。
VSCodeのDockerコンテナ上に開発環境を構築できる仕組み(VSCode拡張)です。
参考: Visual Studio Code Dev Containers
Remote Container
Remote ContainerはDev Containerの昔の名称です。
そのため、基本的には「Remote Container = Dev Container」と捉えておけば良いでしょう。
Remote Development
Remote Developmentは、下記3つの拡張がセットになったVSCode拡張のことです。
- Dev Containers
- Remote SSH
- WSL
参考: Visual Studio Code Remote Development Extension Pack
今回はDev Containerを単体で使うので、Remote Developmentを入れる必要はありません。
VSCodeのDev Containerを使った開発環境の構築方法
ここからは実際にDev Containerを使ってLaravelの開発環境を構築してみます。
まずは、以下の記事を参考にして、普通にDockerとDocker Composeを使ってLaravelが動作する環境を作ります。
プロジェクトのdocker/Dockerfileに以下の内容を記述します。
FROM php:8.0-apache COPY --from=composer:latest /usr/bin/composer /usr/bin/composer RUN apt-get update && apt-get install -y \ git \ && docker-php-ext-install pdo_mysql RUN sed -i 's!/var/www/html!/var/www/devcontainer-laravel/app/public!g' /etc/apache2/sites-available/000-default.conf
compose.yamlに以下の記述を追加します。
services: app: build: ./docker ports: - 8080:80 volumes: - .:/var/www/devcontainer-laravel db: image: mysql:8.0 ports: - 3306:3306 environment: MYSQL_DATABASE: database MYSQL_USER: user MYSQL_PASSWORD: pass MYSQL_ALLOW_EMPTY_PASSWORD: "1"
これにより、ローカルのVSCode上にアプリのコンテナを立ててLaravelの開発ができるようになりました。
次に、このアプリをVSCodeのDev Container上に構築していきます。
まずは、VSCodeに下記のDev Containers拡張を追加します。
Visual Studio Code Dev Containers
そして、.divcontainer/devcontainer.jsonに以下の記述を追加します。
{ "name": "Laravel Dev Container", "dockerComposeFile": ["../compose.yaml"], "service": "app", "forwardPorts": [8080], "workspaceFolder": "/var/www/devcontainer-laravel/app", "customizations": { "vscode": { "settings": { "editor.tabSize": 2 }, "extensions": [ "felixfbecker.php-intellisense", "bmewburn.vscode-intelephense-client" ] } }, "updateContentCommand": "composer install && cp .env.example .env && php artisan key:generate" }
簡単に中身の説明をします。
- name: Dev Container の名前です
- dockerComposeFile: Docker Composeの構成ファイルのパスを指定します。この場合、
../compose.yaml
という相対パスが指定されており、親ディレクトリにあるcompose.yaml
ファイルを使用してDockerコンテナを構築します - service: Docker Composeを使用する場合は必須の設定です。Dev Container実行時に接続するDocker Compose内のサービス名を指定します。今回は接続したときにLaravelのコンテナに入りたいので、appを指定しています
- forwardPorts: Dockerコンテナ内で実行されるアプリケーションのポートをホストマシンのポートにフォワードするためのポート番号のリストです。この例では、
8080
ポートがホストマシンの8080
ポートにフォワードされます。これにより、ブラウザからDev Container上のアプリにlocalhost:8080でアクセスできます - workspaceFolder: Dockerコンテナ内でのワークスペースのパスを指定します。この場合、
/var/www/app
というパスが指定されています。 - customizations: Dev Containerの構成をカスタマイズするためのオブジェクトです。
- vscode: Visual Studio Codeの設定を変更するためのオブジェクトです。
- settings: Visual Studio Codeのエディタ設定を変更するためのオブジェクトです。この例では、タブサイズを2に設定しています。
- extensions: Visual Studio Codeにインストールされる拡張機能のリストです。この例では、PHPのサポートに関する拡張機能である
felixfbecker.php-intellisense
とbmewburn.vscode-intelephense-client
が指定されています。他に必要な拡張があればここに追記するようにしましょう
- vscode: Visual Studio Codeの設定を変更するためのオブジェクトです。
- updateContentCommand: コンテナ内で開発環境を更新するためのコマンドを指定します。具体的には、Laravel プロジェクトの依存関係をインストールする composer コマンド、
.env.example
ファイルを.env
にコピーするコマンド、そしてアプリケーションキーを生成する Artisan コマンドが順番に実行されます。
その他、devcontainer.jsonに設定可能な項目やupdateContentCommand等のライフサイクルコマンドについては以下のリンクを参考にしてください。
さらに、Gitの設定も追加します。
これをしておかないと、Dev Container内でgit pushなどができません。
Macを使用している場合は、以下のようにssh-agentにGitの秘密鍵を登録しておくだけで大丈夫です。
ssh-add $HOME/.ssh/id_rsa
これにより、Dev Containerを立ち上げた際に、ssh-agentが秘密鍵をコンテナ内と安全に共有してくれます。
環境ごとのDev Containerに対するGitの設定方法は、以下の記事を参考にしてください。
Sharing Git credentials with your container
ここまで設定できたら、Dev Containerを立ち上げます。
「Dev Containers: Rebuild and Reopen in Container」もしくは「Dev Containers: Reopen in Container」を実行してください。
実行したらDev Containerが立ち上がって、VSCodeの画面がDev Containerのものに切り替わるはずです。
この状態でlocalhost:8080にアクセスすると、Laravelの画面が表示されます。
GitHub CodespacesとDev Containerを使った開発環境の構築方法
ここまででVSCode上でDev Containerを構築することはできました。
次に、このDev ContainerをGitHub Codespaces上で動かしてみます。
これにより、ローカルPCのスペック等に影響されることのない開発環境を構築することができます。
まずは、先ほどdevcontainer.jsonを作成したリポジトリのページに移動します。
そして、Create codespaces on mainを選択します。
すると次のようにDev Containerがビルドされます。
少し待てば、以下のようにブラウザ上でGitHub Codespaces上に構築したDev ContainerのIDEの画面が表示されるはずです。
このアプリケーションのビルド(Dockerfileのbuildやパッケージのインストールなど)には時間がかかることが多いです。
そこで使える便利な機能が、「プレビルド」です。
定期的にプレビルドをしておくことで、新しくCodespacesを新たに作成したときに、Dockerfileのビルドやパッケージのインストールを待つことなく、すぐに開発を開始することができます。
プレビルドの頻度は、「mainにpushしたとき」「1時間に一度」など自由に選択することができます。
少しでも環境構築の手間を減らしたい人は活用するようにしましょう。
composer install等のコマンドをプレビルドの中で実行したい場合、devcontainer.jsonのpostCreateCommand
コマンドに指定してしまうと、composer installは実行されません。
プレビルドの中でコマンドを実行したい場合は、onCreateCommand
や updateContentCommand
コマンドを使うようにしましょう。
参考: プレビルドのプロセス
ここまでできたら、ターミナルの「ポート」に表示されているアドレスにアクセスします。
ポート8080が特定のアドレスに転送されています。
Laravelの画面が表示されます。
GitHub Codespaces上で開発する場合は、Gitのプライベートキー等の設定をする必要はありません。
コードを変更した後にコミットをして、以下のように「同期」のボタンを押したら、それがそのままリポジトリに反映されます。
このようにGitHubと開発環境の距離が近いのもGitHub Codespacesを使う大きなメリットの一つです。
このままChrome等のブラウザ上で開発することも可能ですが、VSCodeからGitHub Codespacesに接続して開発をすることもできます。
VSCodeに以下の拡張を追加します。
Remote ExplorerにGitHub Codespacesが表示されるので、接続します。
すると、以下のようにローカルのVSCodeからGitHub Codespaces上のDev Containerにアクセスして開発を進めることができます。
ローカルからGitHub Codespacesに接続した場合も、gitのキーの設定等は必要ありません。
開発内容をコミットしてgit pushすれば、そのまま変更内容が反映されます。
今回はdevcontainer.jsonでphp artisan key:generate
はコマンドを使ってアプリケーションキーを設定していますが、Codespacesのsecretsに環境変数を設定して、.envでそれを使わせるようにすることも可能です。
これを利用することで、秘匿情報などを柔軟に利用して開発環境を構築することができます。
GitHub CodespacesとDev Containerのまとめ(メリットデメリット)
ここまででDev containerやGitHub Codespacesについてはある程度イメージがついたはずです。
ここで、これまでの内容も含めて、「Dev Containerを利用しないDocker開発環境」「VSCode上に構築するDev Container環境」「GitHub Codespaces上に構築するDev Container環境」のそれぞれのメリット・デメリットをまとめてみます。
- メリット
- アプリケーション実行環境のポータブル性が高まる
- デメリット
- 開発環境の設定(VSCode拡張のインストールなど)は各開発者がする必要がある
- 環境構築に時間がかかる場合がある
- 開発者のマシンの状態により、環境が立ち上がったり立ち上がらなかったりする
- 「Macだと動くけどWindowsだと動かない」「Intel Macだと動くけどM1 Macだと動かない」など
- プロジェクトとごとに必要なパッケージやVSCodeの拡張が異なり、切り替えが面倒
- ローカル環境の汚染。何を入れたか覚えていない
- PCを新調・初期化する度に環境構築が必要
- 開発環境の設定(VSCode拡張のインストールなど)は各開発者がする必要がある
- メリット
- アプリケーション実行環境と開発環境のポータブル性が高まる
- 環境構築の速度が上がる
- 最初からコンテナに入った状態で開発をスタートできる
- 今どういう環境で開発しているのかファイルで確認でき、バージョン管理も容易になる
- ローカルマシンへの影響を心配することなく、異なる開発環境間で素早く切り替えができる
- デメリット
- パフォーマンスが個人のPCスペックに依存する
- 環境構築がVSCodeに限定される(Dec Container CLIもあるが、VSCode拡張等の設定は使えない)
- 通常のアプリケーションコンテナ以上にメモリを消費する
- ssh-agentを使ってgitのプライベートキーをDev Container内に共有する必要がある
- メリット
- アプリケーション実行環境と開発環境のポータブル性が高まる
- パフォーマンスが個人のPCスペックや環境に依存しない
- GitHubが用意したサーバー上に環境を作れる
- GitHubとの親和性が高い
- 起動した時点で開発向けの設定が行われている
- ソースコードのclone
- GitHub へのアクセス設定
- 環境変数の登録
- gitのキー設定が不要
- 起動した時点で開発向けの設定が行われている
- デメリット
- ネットワーク遅延があれば開発が滞る可能性
- GitHubが落ちたら使えない(インターネット接続が必須)
- GitHub Codespacesの利用にお金がかかる
基本的には、GitHub Codespaces上にDev Containerを構築することで、最も快適な開発環境を構築できます。
ただし、Codespacesにはコストがかかるのと、GitHubが落ちたら開発できなくなるなどのデメリットもあるので、その辺りのメリットデメリットを天秤にかけた上で開発環境の選定をするのが大切です。
おわりに
今回はGitHub CodespacesとDev Containerを使った環境構築の方法とメリットをお伝えしてきました。
個人的には、環境構築はシンプルな手順であればあるほど、必要な時間が短ければ短いほど良いと考えています。
そして、究極的には「環境構築」という概念すら消えて、プロジェクトにアクセスしたらそのまま開発に入れるのが理想だと考えています。
なぜなら、「環境構築の容易さ」はアプリケーションの保守性に直結するからです。
開発を始めるまでに膨大で複雑な手順が必要なアプリケーションなど、誰も開発や保守をしたいとは思わないでしょう。
その意味で、今回紹介した「Dev Container」や「GitHub Codespaces」は、そんな理想に我々を近づけてくれるツールだと考えています。
ぜひ自身のプロジェクトでも活用してみてください!
今回は以上となります。
最後まで読んでいただきありがとうございました。
この記事が開発環境のクオリティを上げる上で少しでも参考になっていれば幸いです。
参考資料
- Dev Containers tutorial
- Developing inside a Container
- GitHub Codespaces
- GitHub Codespaces Docs
- Sharing Git credentials with your container
- 開発コンテナーの概要
- GitHub Codespaces のプレビルドについて