👩‍💻

VSCodeを活用した現代Web開発環境構築ガイド ~launch.json, tasks.json, DevContainer~

2024/02/04に公開

はじめに 📘

この記事では、VSCode を用いた開発環境の構築案を、
ローカル環境、Docker Compose、そしてDocker Composeと DevContainer を組み合わせたアプローチを含む三つのシナリオに分けて紹介します。

使用技術について ⚙️

  • tasks.json
    • 特定のコマンドの自動実行を設定するために使用されます。ビルドプロセス、テスト実行、リント処理など、開発プロセスの一部として頻繁に実行されるタスクを管理します。
  • launch.json
    • アプリケーションのデバッグ設定を管理します。デバッグセッションの開始方法、環境変数の設定、デバッグタイプのカスタマイズに利用されます。
  • Docker Compose
    • 複数のコンテナを定義し、実行するためのツールです。開発、テスト、本番環境を一貫して管理することが可能になります。
  • DevContainer
    • VSCodeの機能の一つで、Dockerコンテナ内で完全な開発環境を構築し、使用することが可能です。コードの編集やデバッグをコンテナ内で直接行えるため、開発環境の一致性と再現性を高めます。

環境構成案 📝

1️⃣ launch.json, tasks.json (local)

前提

開発陣全員がvscodeを使用している。

構成の意図

  • 開発環境の即時セットアップ
    • 追加のツールやコンテナの構築なしに、すぐに開発を開始できる
  • シンプルなデバッグプロセス
    • VSCodeのlaunch.jsontasks.jsonを使用して、直感的かつ簡単にデバッグセッションを開始できる

ディレクトリ構成

├── .vscode
│   ├── launch.json
│   ├── tasks.json
│   └── settings.json
├── my-react-app
│   ├── node_modules/...
│   ├── README.md
│   ├── package-lock.json
│   ├── package.json
│   ├── public/
│   └── src/
└── my_django_app
    ├── .venv/...
    ├── db.sqlite3
    ├── manage.py
    ├── my_django_app/
    ├── poetry.lock
    └── pyproject.toml
ディレクトリのセットアップ方法
npx create-react-app my-react-app

poetry add django
poetry run django-admin startproject my_django_app
# djangoのプロジェクトに関してはコードは変更してませんが、ディレクトリを一部変更してます

ファイルの内容

launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch React App",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}/my-react-app",
      "preLaunchTask": "npm start",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack:///src/*": "${webRoot}/*"
      }
    },
    {
      "name": "Django: Runserver",
      "type": "python",
      "request": "launch",
      "program": "${workspaceFolder}/my_django_app/manage.py",
      "args": ["runserver"],
      "django": true,
      "justMyCode": false,
      "env": {
        "DJANGO_DEBUG": "true"
      },
      "cwd": "${workspaceFolder}"
    }
  ]
}
tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "npm start",
      "type": "npm",
      "script": "start",
      "path": "my-react-app",
      "detail": "react-scirpts start",
      "isBackground": true,
      "problemMatcher": {
        "owner": "custom",
        "pattern": [
          {
            "regexp": "^(.*):(\\d+):(\\d+) - error TS(\\d+): (.+)$",
            "file": 1,
            "line": 2,
            "column": 3,
            "code": 4,
            "message": 5
          }
        ],
        "background": {
          "activeOnStart": true,
          "beginsPattern": ".*Compiling.*",
          "endsPattern": ".*Compiled successfully.*"
        }
      },
      "presentation": {
        "reveal": "always",
        "panel": "new"
      },
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}
settings.json
# debug時にpythonの仮想環境を認識できるように設定
{
  "python.defaultInterpreterPath": "my_django_app/.venv/bin/python"
}

開発時の環境構築

# django
cd my_django_app/django
poetry install

# react
cd my-react-app/react
npm install

動作確認・Debug

  1. vscodeの実行とデバッグを選択
  2. 下記のようにlaunch.jsonで指定したnameが追加されているためデバッグしたいアプリケーションを選択して起動

実行とデバッグ launch

2️⃣ launch.json with docker-compose

前提

開発陣が様々なIDEを使用している

構成の意図

  • 環境の一貫性
    • Docker Composeを使用して、開発者間で完全に一致する開発環境を共有し、「私のマシンでは動作する」問題を解消します。
  • 開発と本番環境の整合性
    • 本番環境に近い状態で開発環境を構築し、本番環境での予期しない挙動を減少させます。
  • クロスプラットフォーム互換性
    • Windows、macOS、Linux間で互換性のある環境を提供し、異なるOSを使用する開発者も同じ条件で作業できます。
  • IDEの選択自由度
    • VSCode以外のIDEでも、Dockerコンテナ上でのデバッグが可能になるため、開発者の好みに応じたツールを使用できます。これにより、IDEに依存しない 開発環境を実現します。
  • セットアップの迅速化とサービス管理の簡素化
    • 新しい開発者がプロジェクトに参加する際のセットアップ時間を短縮し、複数のサービスを簡単に管理できます。

ディレクトリ構成

├── .vscode
│   └── launch.json
├── docker-compose.debug.yml
├── docker-compose.yml
├── my-react-app
│   ├── Dockerfile
│   ├── README.md
│   ├── package-lock.json
│   ├── package.json
│   ├── public/
│   └── src/
└── my_django_app
    ├── Dockerfile
    ├── db.sqlite3
    ├── manage.py
    ├── my_django_app/
    ├── poetry.lock
    └── pyproject.toml

ファイルの内容

docker-compose.yaml
version: '3.8'
services:
  db:
    image: postgres:latest
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: [YOURDBNAME]
      POSTGRES_USER: [YOURUSER]
      POSTGRES_PASSWORD: [YOURPASSWORD]
  front:
    build: ./my-react-app
    volumes:
      - ./my-react-app/src:/react-app/src
      - ./my-react-app/public:/react-app/public
    ports:
      - "3000:3000"
    environment:
      - CHOKIDAR_USEPOLLING=true
  backend:
    build: ./my_django_app
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./my_django_app/my_django_app:/app/my_django_app
    ports:
      - "8000:8000"
    depends_on:
      - db
volumes:
  postgres_data:
docker-compose.debug.yaml
version: '3.8'
services:
  backend:
    build: ./my_django_app
    command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 manage.py runserver 0.0.0.0:8000 --nothreading --noreload"]
    volumes:
      - ./my_django_app/my_django_app:/app/my_django_app
    ports:
      - "8000:8000"
      - "5678:5678"
/my-react-app/Dockerfile
FROM node:14
WORKDIR /react-app
COPY package.json /react-app/
RUN npm install
COPY . /react-app/
CMD ["npm", "start"]
/my_django_app/Dockerfile
FROM python:3.11 as build

WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN pip install poetry
RUN poetry export --only main --without-hashes -f requirements.txt -o /requirements.txt

FROM python:3.11 as prod
WORKDIR /app
COPY --from=build /requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app/
launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "React: Chrome",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}/my-react-app/src",
      "sourceMaps": true,
      "sourceMapPathOverrides": {
        "webpack:///*": "${webRoot}/*"
      },
    },
    {
      "name": "Django: Attach",
      "type": "python",
      "request": "attach",
      "connect": {
        "host": "localhost",
        "port": 5678
      }
    }
  ]
}

開発時の環境構築

# django
cd my_django_app/django
poetry install

# react
cd my-react-app/react
npm install

動作確認・Debug

  1. Docker Composeを用いて、複数のコンテナ(例: フロントエンド、バックエンド、DB)を同時に起動します。
  2. launch.jsonを通じて、React アプリケーションに接続し Chrome を立ち上げる
  3. launch.jsonを通じて、djangodebugpy の稼働しているポートにアクセス

3️⃣ launch.json with docker-compose with DevContainer

前提

開発陣全員がvscodeを使用している。

構成の意図

  • 開発環境の完全一致性
    • 開発、テスト、本番環境をDockerコンテナを通して一致させ、環境差異による問題を排除します。
  • OSや他の開発環境に依存しない開発
    • 全ての開発者が同じDockerコンテナ上で作業することで、異なるOSやIDE間での互換性問題を解決します。
  • コードの編集やデバッグの直接実行
    • コンテナ内で直接VSCodeを使用し、コードの編集やデバッグを行うことができます。
  • 新メンバーの迅速な環境構築
    • DevContainerの設定をプロジェクトに含めることで、新しい開発者がプロジェクトに参加する際のセットアップ時間を大幅に短縮します。
  • プロジェクト間での環境統一
    • 異なるプロジェクトでも同じDevContainer設定を使用することで、プロジェクト間での開発環境の一貫性を保ちます。

ディレクトリ構成

.
├── .devcontainer
│   ├── backend-container
│   │   ├── devcontainer.json
│   │   └── docker-compose.extend.yml
│   └── front-container
│       ├── devcontainer.json
│       └── docker-compose.extend.yml
├── .vscode
│   └── launch.json
├── docker-compose.debug.yml
├── docker-compose.yml
├── my-react-app
│   ├── .gitignore
│   ├── Dockerfile
│   ├── README.md
│   ├── package-lock.json
│   ├── package.json
│   ├── public/
│   └── src/
└── my_django_app
    ├── Dockerfile
    ├── db.sqlite3
    ├── manage.py
    ├── my_django_app/
    └── requirements.txt

ファイルの内容

2つめの構成から変更/追加になったファイルのみ記載

.devcontainer/backend-container/devcontainer.json
{
    "name": "Django Development",
    # docker-compose.extend.yamlで設定を上書き
    "dockerComposeFile": ["../../docker-compose.yml", "docker-compose.extend.yml"],
    "service": "backend",
    "workspaceFolder": "/app",
    "shutdownAction": "stopCompose",
    "remoteEnv": {
        "PATH": "${containerEnv:PATH}:[/some/other/path]",
        "MY_REMOTE_VARIABLE": "[some-other-value-here]",
    },
    "customizations": {
        "vscode": {
            # 追加したい拡張機能をここに記載
            "extensions": ["streetsidesoftware.code-spell-checker"]
        }
    },
    # 起動前に実行したいコマンドを記載
    "postStartCommand": "echo start"
}
.devcontainer/backend-container/docker-compose.extend.yml
version: '3.8'
services:
  backend:
    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "while sleep 1000; do :; done"
.devcontainer/front-container/devcontainer.json
{
    "name": "React Development",
    "dockerComposeFile": ["../../docker-compose.yml", "docker-compose.extend.yml"],
    "service": "front",
    "workspaceFolder": "/react-app",
    "shutdownAction": "stopCompose",
    "remoteEnv": {
        "PATH": "${containerEnv:PATH}:/some/other/path",
        "MY_REMOTE_VARIABLE": "some-other-value-here",
    },
    "customizations": {
        "vscode": {
            "extensions": ["streetsidesoftware.code-spell-checker"]
        }
    },
    "postStartCommand": "echo start"
}
.devcontainer/front-container/docker-compose.extend.yml
version: '3.8'
services:
  front:
    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "while sleep 1000; do :; done"

開発時の環境構築

  1. command + shift + p (検索窓)
  2. DevContainers: Reopen in Container を選択肢、開発したいアプリケーションを選択(front/backend)
  3. 選択したアプリケーションのコンテナ環境で vscode が開くため、その環境で開発を行う。

動作確認・Debug

  1. Docker Composeを用いて、複数のコンテナ(例: フロントエンド、バックエンド、DB)を同時に起動します。
  2. launch.jsonを通じて、React アプリケーションに接続し Chrome を立ち上げる
  3. launch.jsonを通じて、djangodebugpy の稼働しているポートにアクセス

パラメーターの説明

launch.json

パラメータ 説明
type デバッグセッションのタイプを指定します(例: python, node, pwa-chrome)。
request デバッグセッションの要求タイプを指定します(launchまたはattach)。
program デバッグするプログラムのパスを指定します。
args プログラムに渡される引数のリストを指定します。
env デバッグセッション中に使用される環境変数を指定します。
cwd デバッグセッションの現在の作業ディレクトリを指定します。
django Djangoプロジェクトのデバッグ時に特有の設定を有効にします(true/false)。
justMyCode ユーザーのコードのみをデバッグするかどうかを指定します(true/false)。
sourceMaps ソースマップの使用を制御します。これをtrueに設定すると、トランスパイルまたはバンドルされたコードをデバッグ時に元のソースコードにマッピングでき、開発者は元のソースコード上でデバッグを行うことができます(true/false)。
sourceMapPathOverrides ソースマップ内のファイルパスをオーバーライドするために使用されます。例えば、"webpack:///src/": "${webRoot}/src/"はwebpack:///src/ パスを持つ参照を、プロジェクトの src ディレクトリ内の実際のソースファイルにマッピングします。sourceMapstrue でも、このオーバーライドがない場合、デバッガーは bundle.js 内のコード位置にブレークポイントを設定し、元のソースファイルへの直接的なマッピングができない場合があります。
preLaunchTask デバッグセッションを開始する前に実行するタスクの label を指定します。
fileLocation "relative": 問題が見つかったファイルのパスは、VSCodeのワークスペースフォルダからの相対パスとして解釈されます。ワークスペースのルートフォルダに対して相対的なファイルの位置を指定するために使用されます。 "absolute": 問題が見つかったファイルのパスは、絶対パスとして解釈されます。特定の環境や設定で絶対パスで問題を指定する必要がある場合に使用されます。

tasks.json

パラメータ 説明
label タスクの名前を指定します。これを使用して launch.json からタスクを参照できます。
type タスクの種類を指定します(例: shell, npm)。
script 実行する npm スクリプトの名前を指定します。
command 実行するコマンドを指定します(typeshell の場合)。
isBackground タスクがバックグラウンドで実行されるかどうかを指定します(true/false)。
problemMatcher problemMatcher は、ビルドやリントのプロセスから生じる問題(エラーや警告)を VSCode に認識させ、問題パネルに表示させるために使用されます。カスタム問題マッチャーを定義することも可能です。詳細はこちら
problemMatcher.owner このパラメータは、問題マッチャーがどの種類に関連付けられているかを指定します。
problemMatcher.pattern 問題を特定するための正規表現パターンを指定します。このパターンは、タスクの出力から問題を抽出するために使用されます。各要素は正規表現パターンと、そのパターンにマッチしたときに問題のどの部分を抽出するかを指定します。
problemMatcher.background.activeOnStart バックグラウンド実行がタスク開始時からアクティブになるかどうかを指定します。true に設定すると、開始時からバックグラウンドで実行されます。
problemMatcher.background.beginsPattern バックグラウンド実行を開始するトリガーとなる正規表現パターンを指定します。タスクの出力にこのパターンが一致した場合、バックグラウンド実行が開始されます。
problemMatcher.background.endsPattern バックグラウンド実行を終了するトリガーとなる正規表現パターンを指定します。タスクの出力にこのパターンが一致した場合、バックグラウンド実行が終了します。
presentation タスクの実行時に VS Code がターミナル出力をどのように扱うかを制御します。この設定は、タスク実行の視覚的な側面をカスタマイズするために使用されます。設定可能なプロパティには reveal, echo, focus, panel, showReuseMessage, clear があります。
group タスクを特定のグループに関連付けるために使用されます。ビルドタスクやテストタスクなど、特定の種類のタスクを簡単に識別し、実行できるようにします。kind(タスクの種類)と isDefault(デフォルトのタスクかどうか)を指定できます。

devcontainer.json

オプション 説明
name コンテナの名前。VSCodeのUIに表示されます。
dockerComposeFile 使用するDocker Composeファイルのパス。複数指定可能です。
service Docker Composeの中で開発環境として使用するサービスの名前。
workspaceFolder コンテナ内でのプロジェクトのワークスペースフォルダのパス。
shutdownAction コンテナを閉じる時の動作(stopComposeはDocker Composeを停止させます)。
remoteEnv コンテナ内で設定される環境変数。PATHのような既存の変数を拡張したり、新しい変数を追加できます。
customizations VSCodeの設定や拡張機能など、開発環境のカスタマイズに関するオプション。"vscode"キーの下に設定します。
postStartCommand コンテナ起動後に自動的に実行されるコマンド。セットアップスクリプトの実行などに利用できます。

参照先ドキュメント

https://code.visualstudio.com/docs/devcontainers/create-dev-container

Discussion