はじめに
こんにちは。サービス開発部の木村です。
アドベントカレンダー2日目の記事として、最近GameWithでDev Containerを導入したので、その経緯や導入時のポイントを紹介します!
Dev Containerとは
Dev Containerとは、開発するアプリケーションだけでなくエディタの拡張機能などの開発環境もまとめてコンテナ化することで、より共通化された開発環境を簡単に再現するための仕組みです。
Dev ContainerはVSCodeやIntelliJ IDEAなどの複数のツールでサポートされていたり、Dev Containerを導入したら開発者全員が利用を強制されるわけではなく恩恵を感じている使いたい人だけが使えるので気軽に導入しやすいです。
Dev Container自体の詳しい説明や導入方法は、公式ドキュメントや多くの記事で紹介されているので今回は触れませんが、各種エディタが提供しているドキュメントを参照するのがわかりやすいのでおすすめです。
- Developing inside a Container using Visual Studio Code Remote Development
- Dev Container の概要 | IntelliJ IDEA ドキュメント
GameWithではVSCodeベースのエディタの利用者が多いため、本記事ではVSCodeベースでの内容になります。
Dev Containerを導入した経緯
今回はバックエンドでFuelPHP、フロントエンドのビルド環境でNode.jsが使用されているモノリシックなWebアプリケーションのリポジトリにDev Containerを導入しました。
元々Dockerでアプリケーション自体はコンテナ化はされていましたが、VSCode拡張機能はローカルマシンにインストールされているPHPやNode.jsを参照してしまうため、結局各言語のバージョン等は開発者ごとに管理が必要な状態でした。
Dev Containerを導入してVSCodeの拡張機能等もコンテナ化して開発環境の管理をもっと楽にしたいという話題がチーム内で出たため、今回試しに導入してみることにしました。
Dev Container導入時のポイント
GameWithでDev Containerの導入を進める際に、実用性を考慮して調整した箇所などをいくつかご紹介します。
複数環境のコンテナ化
導入したリポジトリではローカル開発において2つの環境があり、Dev Containerでもそれらを使い分けれるようにしました。
remote
: 開発環境のDBに接続して開発をするための環境local
: ローカルマシン内でDBを立ち上げて、外部とは接続せずに開発するための環境
Dev Containerで複数環境を使い分けるには、次のように/.devcontainer
内をディレクトリで区切り、それぞれにdevcontainer.json
を設置することで、コンテナ起動時に開発者が環境を選んでコンテナを起動できます。
/.devcontainer/ ├─ local/ │ └─ devcontainer.json └─ remote/ └─ devcontainer.json
Named volumeでコンテナのパフォーマンスを改善
Dev Containerを試している際に、コンテナ起動後にgitがつかえるようになるまで長く時間がかかってしまう問題がありました。git status
に20秒以上、git push
にも10秒以上かかってしまい、開発が円滑にできるとは言えない状態でした。git以外のツールにも若干影響はありましたが、gitへの影響が顕著に出ていました。
この問題の原因は、コンテナ内のファイルが多すぎるせいでgitのファイル追跡に時間がかかっているようでした。そのため、次のようにnode_modules
や各種ツールのキャッシュ系ファイルなどのgitで追跡しない大量なファイルが生成されるディレクトリを、次のようにdevcontainer.json
のmounts
で別のvolumeとしてマウントさせることで改善できました。
{ ... "mounts": [ "source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume", ... ] }
開発作業特化のコンテナ調整
既存のDockerコンテナはあくまでもアプリケーションを動かすため環境で、そのまま開発で使うと不便な点もありました。次は一例です。
- コンテナにvimなどのエディタがインストールされていなく、デフォルトで
git rebase
等ができない - コンテナのターミナルで日本語の表示・入力ができない
そのためDev Container専用のコンテナの設定を用意し、アプリケーション用のコンテナを上書きしています。
既存のアプリケーション用のdocker-compose.yml
は大まかに次のようになっており、DB関連のコンテナも一緒に立ち上げています。(各コンテナの詳細な設定は省略しています。)
# /docker/remote/docker-compose.yml version: "3.7" services: nginx: image: nginx restart: always app: build: context: . dockerfile: infrastructure/docker/Dockerfile-app volumes: - .:/var/www/gamewith working_dir: /var/www/gamewith db: build: context: . dockerfile: infrastructure/docker/Dockerfile-mysql memcached: build: context: . dockerfile: infrastructure/docker/Dockerfile-memcached redis: build: context: . dockerfile: infrastructure/docker/Dockerfile-redis
今回調整したかったのはDev Containerで実際にアクセスするapp
コンテナのみなので、次のように/.devcontainer/docker-compose.yml
を作成し、app
コンテナだけDev Container用のDockerfile
を参照するように設定しています。こうすることで上書きされていないdb
やredis
コンテナは引き続き既存のDockerfile
を参照してくれます。
# /.devcontainer/docker-compose.yml version: "3.7" services: app: image: app build: context: . dockerfile: .devcontainer/Dockerfile-app volumes: - .:/var/www/gamewith working_dir: /var/www/gamewith
Dev Container用に作成した/.devcontainer/Dockerfile-app
では次のように、既存のアプリケーションの設定に加えて、vimやlocaleのセットアップをしています。
# /.devcontainer/Dockerfile-app FROM php:8.1-apache-bullseye # アプリケーションに必要な設定やツールのインストール ...省略 # PHPアプリケーションのランライムでは使用しないけど、コンテナのターミナルで実行したい人向けのNode.jsなどをインストール ...省略 # git rebaseなどできるようにvimをインストール RUN apt-get install -y vim # DevContainerのターミナルで日本語が使用できるように、コンテナのlocaleを日本語に設定する RUN apt-get install -y locales \ && sed -i '/ja_JP.UTF-8/s/^# //g' /etc/locale.gen \ && locale-gen \ && update-locale LANG=ja_JP.UTF-8 ENV LANG=ja_JP.UTF-8 ENV LANGUAGE=ja_JP:ja ENV LC_ALL=ja_JP.UTF-8
そして/.devcontainer/docker-compose.yml
を適用するには、devcontainer.json
のdockerComposeFile
でdocker-compose.yml
のパスを優先度が低い順に定義します。(一部コンテナのみを上書きするのではなく、全てDev Container用のコンテナを使用する場合は、既存のdocker-compose.ymlを定義する必要はありません。)
{ "name": "Remote Container", "dockerComposeFile": [ "../../dokcer/remote/docker-compose.yml", // 既存のアプリケーションのdocker-compose.yml "../docker-compose.yml" // Dev Container用のdocker-compose.yml ] }
こうすることで、Dev Containerで起動した時のみapp
コンテナに開発作業用packageのインストールや設定を行うことができます。
ただし、あまりにも実際にアプリケーションを動作させる環境と乖離しすぎてしまうとコンテナ開発をしている意味が無いので、用法・用量は守りましょう。
おわりに
Dev Containerを導入してみて下記が改善されました。
- ローカル開発において、今まで以上におま環が発生しにくくなった。
- PC交換時などのセットアップ時も必要な手順が減って楽になった。
- ローカルマシンのグローバルを参照してしまうことで問題が発生してしまうVSCode拡張機能の挙動を避けれるようになった。
そして、逆に運用少し難しいと思っていることもあります。
- 個人で利用したい拡張機能の管理に若干手間がかかる。
- 手間なのは主に初回セットアップ時や新しく拡張機能を使用する時だけなので、そこまで大きな問題ではありません。
- こちらに関してはまた個別で記事にする予定です!
- パフォーマンスの改善はしているものの、まだローカルに比べてツール系の動作が遅いケースがあるので調整が必要。
総合的に開発体験は良くなったので、調整を続けて他のリポジトリでも積極的に導入しようと思っています。
Dev Containerの導入を検討している方は改めてぜひお試しください!
こんなGameWithではエンジニアを絶賛募集中です!
サーバーエンジニアやフロントエンジニアの方、AIに興味がある方や、Unityでの開発に興味がある方もお気軽にカジュアル面談をお申し込みください!