Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

モノレポ × DevContainere 設計パターン

Avatar for abimaru abimaru
December 19, 2025

モノレポ × DevContainere 設計パターン

スリーシェイク
エンジニア勉強会用資料です。

Avatar for abimaru

abimaru

December 19, 2025
Tweet

More Decks by abimaru

Other Decks in Technology

Transcript

  1. 今日お話しすること 1. 前提知識 - VS Code ワークスペースとは 2. 2つのパターン -

    単一 vs サービス別 DevContainer 3. 詳細比較 - 開発体験・拡張機能・運用面 4. パターン2を選ぶ理由 - サービス別DevContainerの利点 5. 実装例 - 具体的なファイル構成 6. まとめ 2
  2. 前提知識: VS Code ワークスペースとは ワークスペース = VS Code が開いているフォルダ VS

    Code で /my-project を開く ↓ /my-project がワークスペースになる ↓ - ファイルツリーのルートは /my-project - ターミナルの初期ディレクトリは /my-project - 拡張機能は /my-project を基準に動作 4
  3. なぜワークスペースが重要か 多くの VS Code 拡張機能は、ワークスペースのルートを基準に動作します。 拡張機能 参照するファイル 期待する場所 ESLint .eslintrc

    ワークスペースルート Prettier .prettierrc ワークスペースルート TypeScript tsconfig.json ワークスペースルート Tailwind CSS tailwind.config.js ワークスペースルート モノレポの課題: ルートを開くと設定ファイルが複数の場所にあり、拡張機能が正しく動作しないことがある 5
  4. 設定で回避できるが、面倒 .vscode/settings.json で設定ファイルのパスを指定すれば動かせる { "eslint.workingDirectories": ["frontend", "backend"], "prettier.configPath": "frontend/.prettierrc", "typescript.tsdk":

    "frontend/node_modules/typescript/lib" } この方法の問題 拡張機能ごとに設定が必要 frontend/backendで設定が異なると複雑化 新規拡張機能追加時に設定追加が必要 ワークスペースを分ける利点 拡張機能がデフォルトで正しく動作 .vscode/settings.json がシンプルに 設定ミスによるトラブルが減る 6
  5. DevContainer とワークスペースの関係 DevContainer では workspaceFolder で、コンテナ内のどのパスをワークスペースにするかを指定します。 { "workspaceFolder": "/app/frontend" }

    この設定により: VS Code は /app/frontend をワークスペースとして開く ファイルツリーには /app/frontend 以下が表示される 拡張機能は /app/frontend を基準に動作 7
  6. モノレポの DevContainer、2つのパターン monorepo/ ├── frontend/ ├── backend/ └── compose.yml パターン1:

    単一 DevContainer(全部入り) .devcontainer/ └── devcontainer.json ← 1つだけ モノレポ全体を1つの DevContainer で開く パターン2: サービス別 DevContainer .devcontainer/ ├── frontend/ │ └── devcontainer.json └── backend/ └── devcontainer.json 各サービス用に別々の DevContainer を用意 9
  7. パターン1: 単一 DevContainer の設定 { "workspaceFolder": "/app", "customizations": { "vscode":

    { "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "ms-python.python", "golang.go" ] } } } 特徴: 全ての言語・ツールの拡張機能を一度にインストール 10
  8. パターン2: サービス別 DevContainer の設定 // frontend/devcontainer.json { "workspaceFolder": "/app/frontend", "customizations":

    { "vscode": { "extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] } } } // backend/devcontainer.json { "workspaceFolder": "/app/backend", "customizations": { "vscode": { "extensions": ["golang.go"] } } } 特徴: 各サービスに必要な拡張機能のみをインストール 11
  9. パターン2を選ぶ理由1: 拡張機能の最適化 例: TypeScript + Go + Python のモノレポ monorepo/

    ├── frontend/ # TypeScript, React ├── backend/ # Go └── data/ # Python パターン1(単一) { "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "golang.go", "ms-python.python", "ms-python.vscode-pylance" ] } → 全ての言語サーバーが起動 パターン2(サービス別) // frontend { "extensions": ["vscode-eslint"] } // backend { "extensions": ["golang.go"] } // data { "extensions": ["ms-python.python"] } → 必要な拡張機能だけ 17
  10. パターン2を選ぶ理由2: 担当領域への集中 ファイルツリーに関係ないコードが表示されないため、集中しやすい パターン1: 全ファイル表示 ├── frontend/ │ └── src/(100ファイル)

    ├── backend/ │ └── src/(100ファイル) └── ... パターン2: 担当分だけ表示 frontend の DevContainer: └── src/(100ファイル)← これだけ 18
  11. ディレクトリ構成 . ├── .devcontainer/ │ ├── backend/ │ │ ├──

    devcontainer.json # backend用の設定 │ │ └── compose.yml # backend用のオーバーライド │ └── frontend/ │ ├── devcontainer.json # frontend用の設定 │ └── compose.yml # frontend用のオーバーライド ├── backend/ # バックエンドコード ├── frontend/ # フロントエンドコード ├── compose.yml # 共通のDocker Compose設定 └── Dockerfile.local # 共通の開発用イメージ 23
  12. Dockerfile.local(共通の開発用イメージ) FROM mcr.microsoft.com/devcontainers/base:bookworm # mise(ツールバージョン管理)のセットアップ RUN apt-get update \ &&

    apt-get -y --no-install-recommends install \ sudo curl git postgresql-client ca-certificates build-essential \ && rm -rf /var/lib/apt/lists/* SHELL ["/bin/bash", "-o", "pipefail", "-c"] ENV MISE_DATA_DIR="/root/.mise" ENV MISE_CONFIG_DIR="/root/.mise" ENV MISE_CACHE_DIR="/root/.mise/cache" ENV MISE_INSTALL_PATH="/usr/local/bin/mise" ENV PATH="/root/.mise/shims:$PATH" # miseのインストール RUN gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 0x7413A06D \ && curl https://mise.jdx.dev/install.sh.sig | gpg --decrypt > install.sh \ && sh ./install.sh USER root 24
  13. compose.yml(共通設定) services: postgres: image: postgres:15-alpine environment: POSTGRES_DB: myapp POSTGRES_USER: myapp

    POSTGRES_PASSWORD: password volumes: - postgres-data:/var/lib/postgresql/data backend: build: dockerfile: Dockerfile.local volumes: - .:/app - mise:/root/.mise - backend-node-modules:/app/backend/node_modules environment: DATABASE_URL: postgresql://myapp:password@postgres:5432/myapp working_dir: /app/backend command: bash -c "mise trust -a && mise install --yes && pnpm install && pnpm dev" frontend: build: dockerfile: Dockerfile.local volumes: - .:/app - mise:/root/.mise - frontend-node-modules:/app/frontend/node_modules working_dir: /app/frontend command: bash -c "mise trust -a && mise install --yes && pnpm install && pnpm dev" volumes: postgres-data: mise: backend-node-modules: 25
  14. .devcontainer/frontend/devcontainer.json { "name": "frontend", "dockerComposeFile": [ "../../compose.yml", "compose.yml" ], "service":

    "frontend", "workspaceFolder": "/app/frontend", "remoteUser": "root", "customizations": { "vscode": { "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode" ], "settings": { "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" } } }, "forwardPorts": [5173] } 26
  15. .devcontainer/frontend/compose.yml(オーバー ライド) services: frontend: command: sleep infinity なぜ sleep infinity

    か: ルートの compose.yml では pnpm dev が実行される DevContainer では、VS Code 接続後にターミナルでコマンドを実行したい sleep infinity でコンテナを待機状態に保つ 27
  16. 設定の流れ 1. VS Code で「Open Folder in Container」を選択 2. .devcontainer/frontend

    を選択 3. DevContainer が以下を実行: - compose.yml を読み込む - .devcontainer/frontend/compose.yml でオーバーライド - frontend サービスに接続 - /app/frontend をワークスペースとして開く - 指定された拡張機能をインストール 28
  17. カスタマイズ: ワークスペースをルートにしたい 場合 パターン2 をベースに、ワークスペースだけルートにすることも可能 { "workspaceFolder": "/app", // ルートを開く

    "service": "frontend" // 接続先は frontend コンテナ } これにより: ファイルツリーには全ファイルが表示 拡張機能は frontend 用のみインストール Git 操作もコンテナ内で可能 29