80
107

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

チームで開発するならDev Containersで環境構築工程をスキップしませんか?

Posted at

読み飛ばしてください

みなさまどうも。
限界派遣SESと言われて心が折れるnikawamikanです。

最近、学生さんと一緒になんやかんや開発することがあり、その中で使ってみてよかった技術の中にDev Cointanersと言われる技術があります。
VSCode限定ではありますが、開発環境の差異を可能な限り埋めてくれるスゴイやつです。

さらに言えば新たにチームに参加するメンバーに開発環境の構築を逐一説明する必要もなくなるので、入れ替わりの激しい限界派遣SESにこそ使う技術です。

本題

前提として以下の環境はインストールされているものとします。

  • Docker
  • docker compose (WindowsやMacの場合DockerDesktopをインストールしているのでインストール不要のはずです)
  • VSCode

OSは上記がインストールできるのであればわりとなんでもOKだと思います(例外はどこにでもあるので断言はしません)

Dev Containersで環境構築を行うというのはどういうことか?

例えば私のgithubにあるdiscord BotのテンプレートではPycordというdiscord.pyのフォークされたライブラリを利用して開発を行うテンプレートを定義しているのですが、これを使うことでDockerとVSCodeがインストールされた環境であれば特定のLinuxディストリビューションにPythonの指定バージョンのインストールやライブラリの指定バージョンのインストールなどがDockerの仮想環境上に構築されPythonに必要なVSCodeの拡張機能のインストールまでが自動で行われます。

つまり、すでに存在しているrepositoryから環境構築にかかる時間はせいぜいgit clone + コンテナをビルドする時間程度で実際に行う作業はほとんどありません。

あとは数行のコードを記述すればBOTを実行することも可能ですし。第三者のコントリビューターが環境構築をする手間もかなり省けると言えます。

Dev Containersで環境構築をしていく

実際に環境構築をしていきましょう。

VSCodeにDev Containersをインストールします。
この拡張機能をインストールすることで前提となるRemote - SSHのインストールも行われるはずです。

次にDev Containerの設定フォルダを作成します。(この時のディレクトリは適宜プロジェクトごとに設定するなどしてください)
これはVSCode左下にあるリモート ウィンドウを開きますと表示されているアイコンをクリックし、開発コンテナー構成ファイルを追加をクリックすることで対話式のプロンプトが開始されます。
image.png
image.png

今回はサンプルとしてNode.js & TypeScriptの環境を構築していきます。
image.png

Apple SiliconのMacでは一部のバージョンでバグが存在しているようなので今回は18-bullseysを選択します。
image.png

追加機能については今回は必要ないのでそのままOKを押します
image.png

すると.devcontainerというフォルダにdevcontainer.jsonというファイルが作成されています。
また右下にコンテナーで再度開くという通知が出てることが確認できます。
image.png

通知は消えてしまうと分からなくなるので、とりあえず見逃してしまったら左下のリモートウィンドウのアイコンをクリックしコンテナーで再度開くを選択します。
image.png

するとDockerのimageが展開され仮想環境にSSH接続された状態と同じ状態が再現されます。
image.png

これでひとまず、ローカル環境を汚さずにNodeの実行環境が用意できました。

Next.jsプロジェクトの作成

このNode環境に対してNext.jsのプロジェクトを作成してみます。

手順は一般的なNext.jsの構築と変わりません。
npx create-next-app@latestのコマンドを実行し対話式のプロンプトに対し適宜入力をしてください。
image.png

一度yarn devコマンドを実行しサーバーを起動します。
image.png

http://localhost:3000をブラウザで開くと実行されていることが確認できます。

image.png

これはRemote SSHの拡張機能により自動的にコンテナ内のPortとlocalhostのPortが紐付けられるためです。
image.png

これによりほぼローカルの環境と変わりなく作業ができることが確認できたかと思います。

拡張機能のインストール

このDev Containersを利用して開発環境を作成すると拡張機能が入っていない状態となります。
これはRemote SSHでサーバー機に接続した状態と一緒といえます。
つまり、コンテナ内に対してSSH接続を行い、VSCode Serverをインストールしている状態となっていると同じといえます。

そのため、拡張機能を新たにインストールする必要があります。

メンドクサイと思ったかもしれませんが、これは余計な拡張機能が入らずクリーンな状態で環境が分けられていると考えると喜ばしいとも言えます。
また、チーム内で共通の拡張機能を使って設定も共有することができます。

実際に拡張機能をインストールしていきます。

共通で利用する拡張機能のインストール

今回のプロジェクトではTailwind CSSを利用していくため、拡張機能としてTailwind CSS IntelliSenseをインストールします。
この時、ここにインストールしただけではdevcontainer.jsonに反映されないため、歯車アイコンからdevcontainer.jsonに追加を選択し、devcontainer.jsonへ記述します。
image.png

するとextensionsの項目が追加されていることが確認できます。
image.png

devcontainer.jsonなど、.devcontainer配下にあるファイルはDockerの環境の設定ファイルなので、変更時は再ビルドするのが好ましいです。(拡張機能のインストールではすでにインストールされている状態だと思うので必要ありませんが)

リビルドは左下のリモート ウィンドウアイコンをクリックしてコンテナーのリビルドを実行します。
image.png

また、tailwindを利用する際は一部で警告が発生するため、これを解消するために.vscodesettings.jsonに以下の記述を追記します。

{
    "files.associations": {
      "*.css": "tailwindcss"
    }
}

個人でのみ利用する拡張機能のインストール

逆に個人でのみしか利用しない拡張機能をdevcontainer.jsonに記述するのは好ましくありません。
なぜなら誰もがCopilotを使えるわけでもありませんし、nyan catプラグインは複数の種類があり好みがあるからです。

image.png

しかし、これらを毎回インストールするのはメンドクサイですし、コンテナをリビルドする度に行う必要があるので、軽く賽の河原の石積みを思わせる苦行を感じることになります。

これを回避するためにDefault Extentionsを設定します。
設定画面の検索欄にdevcontainer defaultなど入力すればすぐに出てきます。
image.png

拡張機能の歯車アイコンから拡張機能IDのコピーをし、IDを貼り付けて追加します。
これにより、あなたの賽の河原に費やす時間を節約できます。

image.png
image.png

ここまでで同じ環境構築複数人で行う不毛な状況を回避することができるようになりました。(DockerとVSCodeのインストールは結局する必要がありますが)

Node.js特有の注意点など

これはNode.js環境特有の問題です。
ただし、docker composeを利用する方法なども掲載するため必要な場合はそれ以外でも参考にしてください。

この環境から開発をしようとすると以下の問題が発生します。

  • サーバーの起動に時間がかかる
  • ホットリロードができない

これらについて一つずつ解説します。

サーバーの起動に時間がかかる

これはnode_modulesの保存先がローカルにあり、それをDockerのコンテナに対してbindする形になっているのが原因です。
そのため、node_modulesのフォルダをDockerのVolumeを利用して管理するように変更します。

先ほど作った.devcontainerに対してcompose.yamlを作成し以下のようにします。

.devcontainer
  ┣━ compose.yaml
  ┗━ devcontainer.json

このcompose.yamlではdevcontainer.jsonに記述されているimageを利用し、volumesの記述などをします。
具体的には以下のようなコードになります。

volumes:
  node_modules:

services:
  main:
    # Docker imageの指定
    image: mcr.microsoft.com/devcontainers/typescript-node:1-18-bullseye
    volumes:
      # ローカルのワークスペースをコンテナのワークスペースにマウント
      - ..:/workspace/app
      # volumeのnode_modulesをコンテナのnode_modulesにマウント
      - node_modules:/workspace/app/node_modules
    # ttyとstdin_openをtrueにするのはbuild時を失敗しないため(ないとすぐ閉じちゃう)
    tty: true
    stdin_open: true

次にこれを利用してDev Containerを構築するために.devcontainerファイルを編集します。
このjsonファイルはコメントが許容されているため必要であればコメントを記述するとわかりやすくなります。

{
	"name": "my project",
	// docker composeのファイル名
	"dockerComposeFile": "compose.yaml",
	// アタッチを行うdocker composeのサービス名
	"service": "main",
	// workspaceをバインドするディレクトリ
	"workspaceFolder": "/workspace/app",
	// node_modulesのディレクトリの所有者をnodeユーザーに変更してからyarnを実行する
	"postCreateCommand": "sudo chown -R node:node ./node_modules && yarn",
	// リモートユーザーをnodeユーザーに変更する
	"remoteUser": "node",
	// 拡張機能のインストール
	"customizations": {
		"vscode": {
			"extensions": [
				"bradlc.vscode-tailwindcss"
			]
		}
	}
}

この状態でコンテナのリビルドを行い再度開発コンテナにアタッチします。
この時、プロジェクトのPathに2byte文字が含まれているとcompose.yamlをbuildするときにエラーとなるため日本語などは含めないようにしてください。

以下のようにビルドに成功していればnode_modulesがDockerのVolume側に作成されている状態となります。
image.png

ホットリロードができない

これはNext.jsだけでなくvueでも同じような現象を確認しています。
不便極まりないのでそれぞれ解決策を提示します。

Next.js の場合

package.jsonファイルにあるscriptsの項目のdevコマンドにWATCHPACK_POLLING=trueの変数を追加し対応します。

これによりホットリロードが行われるようになり、幸せになれます。

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "WATCHPACK_POLLING=true next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
// 中略
}

vueの場合

vue.config.jsファイルのdefineConfigに以下の設定を追加することでホットリロードが可能になります。

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,

  configureWebpack: {
    watchOptions :{
      aggregateTimeout: 300,
      poll: 1000
    }
  },
})

最後に

これにてDev Containers布教は終了です。

実際、私が現在新規でWebアプリやコンソールアプリケーションの環境構築を行っていく中でほとんどの場合Dev Containersを利用して作成しています。
これにより、開発環境の構築のような本質とは無関係な部分でのコンフリクトが起こりにくくなり、円滑なコミュニケーションをとることができ満足しています。

皆さんも開発環境をスキップして快適な開発生活をスタートしましょう!

80
107
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
107

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?