Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
モノレポ × DevContainere 設計パターン
Search
abimaru
December 19, 2025
Technology
400
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
モノレポ × DevContainere 設計パターン
スリーシェイク
エンジニア勉強会用資料です。
abimaru
December 19, 2025
More Decks by abimaru
See All by abimaru
SAM + FastAPI + Mangum でお手軽サーバーレス
kugimiya
0
440
Other Decks in Technology
See All in Technology
ソフトウェアDNAとクラウドエージェントのススメ
cloudace
0
110
Railsのように考える: See through the Master
snoozer05
PRO
3
870
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
180
2026/09/10 Spring Bootから Jakarta EE/MicroProfileへの移行
megascus
0
370
MCPをつなげて作る組織横断のAIエージェント基盤(の開発工程)
tsubakimoto_s
0
130
beyond jj: config & tools ecosystem
indirect
0
440
GoにおけるFFIのこれまでとこれから
goccy
5
3.4k
AI時代の「技術的負債」の変質ー概念の終焉と再解釈、エージェントと共に向かう先
nwiizo
0
2.6k
白金鉱業Meetup Vol.25 アウトカムが二値のデータに対するCausal Impact
brainpadpr
0
200
ユーザー価値を届け続けるためにウォンテッドリーが大切にしている文化
kotaminato
0
160
AI 時代のスタートアップエコシステ厶から考究する技術的負債との向き合い方
m3m0r7
PRO
2
2.1k
Issue 駆動でスペシャリストの意図を届ける、AI 実装のアクセシビリティ向上
thkt
0
110
Featured
See All Featured
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
700
First, design no harm
axbom
PRO
2
1.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
240
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
350
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
360
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
410
Accessibility Awareness
sabderemane
1
210
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Transcript
モノレポ × DevContainer 設計パターンガイド どちらのパターンを選ぶべきか 2025/12/19 エンジニア勉強会 釘宮 大知
今日お話しすること 1. 前提知識 - VS Code ワークスペースとは 2. 2つのパターン -
単一 vs サービス別 DevContainer 3. 詳細比較 - 開発体験・拡張機能・運用面 4. パターン2を選ぶ理由 - サービス別DevContainerの利点 5. 実装例 - 具体的なファイル構成 6. まとめ 2
この発表で解決できること こんな悩みを持っていませんか? モノレポでDevContainerをどう構成すべきか わからない 拡張機能が正しく動作しない frontend/backendで異なる言語を使うときの 最適解がわからない この発表で持ち帰れるもの 2つのパターンの違いと選び方 ワークスペースと拡張機能の関係
パターン2(サービス別)の具体的な実装方 法 目標:チームに最適なDevContainerパターンを選択できるようになる 3
前提知識: VS Code ワークスペースとは ワークスペース = VS Code が開いているフォルダ VS
Code で /my-project を開く ↓ /my-project がワークスペースになる ↓ - ファイルツリーのルートは /my-project - ターミナルの初期ディレクトリは /my-project - 拡張機能は /my-project を基準に動作 4
なぜワークスペースが重要か 多くの VS Code 拡張機能は、ワークスペースのルートを基準に動作します。 拡張機能 参照するファイル 期待する場所 ESLint .eslintrc
ワークスペースルート Prettier .prettierrc ワークスペースルート TypeScript tsconfig.json ワークスペースルート Tailwind CSS tailwind.config.js ワークスペースルート モノレポの課題: ルートを開くと設定ファイルが複数の場所にあり、拡張機能が正しく動作しないことがある 5
設定で回避できるが、面倒 .vscode/settings.json で設定ファイルのパスを指定すれば動かせる { "eslint.workingDirectories": ["frontend", "backend"], "prettier.configPath": "frontend/.prettierrc", "typescript.tsdk":
"frontend/node_modules/typescript/lib" } この方法の問題 拡張機能ごとに設定が必要 frontend/backendで設定が異なると複雑化 新規拡張機能追加時に設定追加が必要 ワークスペースを分ける利点 拡張機能がデフォルトで正しく動作 .vscode/settings.json がシンプルに 設定ミスによるトラブルが減る 6
DevContainer とワークスペースの関係 DevContainer では workspaceFolder で、コンテナ内のどのパスをワークスペースにするかを指定します。 { "workspaceFolder": "/app/frontend" }
この設定により: VS Code は /app/frontend をワークスペースとして開く ファイルツリーには /app/frontend 以下が表示される 拡張機能は /app/frontend を基準に動作 7
ワークスペースの仕組みはわかった。 では、モノレポでどう構成する? → 2つのパターンを紹介 8
モノレポの 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
パターン1: 単一 DevContainer の設定 { "workspaceFolder": "/app", "customizations": { "vscode":
{ "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "ms-python.python", "golang.go" ] } } } 特徴: 全ての言語・ツールの拡張機能を一度にインストール 10
パターン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
各パターンの詳細比較: 開発体験 観点 パターン1(単一) パターン2(サービス別) ファイルツリー 全ファイル見える 担当サービスのみ 拡張機能 全部入り
必要なものだけ ターミナル コンテナ内 コンテナ内 Git操作 コンテナ内で可能 ホスト推奨 12
各パターンの詳細比較: 拡張機能の動作 観点 パターン1(単一) パターン2(サービス別) 設定ファイル検出 複数あると混乱の可能性 正しく検出 言語サーバー 全言語が起動
必要な言語のみ メモリ使用量 多い 少ない 13
各パターンの詳細比較: セットアップと運用 観点 パターン1(単一) パターン2(サービス別) 初期構築の手間 少ない 中程度 設定の重複 なし
一部あり VS Code起動 1ウィンドウ 複数ウィンドウ可 14
チーム規模との相性 チーム構成 おすすめパターン 1人で全部開発 パターン1 少人数で全部触る パターン1 担当が分かれている パターン2 言語が大きく異なる
パターン2 💡 チームの状況やプロジェクトの特性に合わせて選択 15
パターンの違いはわかった。 なぜパターン2を選ぶのか? → パターン2(サービス別)が有効なケース 16
パターン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
パターン2を選ぶ理由2: 担当領域への集中 ファイルツリーに関係ないコードが表示されないため、集中しやすい パターン1: 全ファイル表示 ├── frontend/ │ └── src/(100ファイル)
├── backend/ │ └── src/(100ファイル) └── ... パターン2: 担当分だけ表示 frontend の DevContainer: └── src/(100ファイル)← これだけ 18
パターン2を選ぶ理由3: 疎結合開発との相性 frontend と backend を疎結合で開発する場合、それぞれが独立した開発環境を持つのは自然 frontend 開発者は frontend の
DevContainer を使う backend 開発者は backend の DevContainer を使う 必要なときだけ両方起動 19
トレードオフ: Git 操作 パターン2 では、ワークスペースがサブディレクトリになるため、Git 操作がしにくくなる 対処法: Git 操作はホスト側で行う または、ターミナルで
cd /app してから操作 20
パターン2の利点はわかった。 実際にどう実装する? → 具体的なファイル構成と設定例 21
パターン2の実装例: 全体構成 22
ディレクトリ構成 . ├── .devcontainer/ │ ├── backend/ │ │ ├──
devcontainer.json # backend用の設定 │ │ └── compose.yml # backend用のオーバーライド │ └── frontend/ │ ├── devcontainer.json # frontend用の設定 │ └── compose.yml # frontend用のオーバーライド ├── backend/ # バックエンドコード ├── frontend/ # フロントエンドコード ├── compose.yml # 共通のDocker Compose設定 └── Dockerfile.local # 共通の開発用イメージ 23
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
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
.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
.devcontainer/frontend/compose.yml(オーバー ライド) services: frontend: command: sleep infinity なぜ sleep infinity
か: ルートの compose.yml では pnpm dev が実行される DevContainer では、VS Code 接続後にターミナルでコマンドを実行したい sleep infinity でコンテナを待機状態に保つ 27
設定の流れ 1. VS Code で「Open Folder in Container」を選択 2. .devcontainer/frontend
を選択 3. DevContainer が以下を実行: - compose.yml を読み込む - .devcontainer/frontend/compose.yml でオーバーライド - frontend サービスに接続 - /app/frontend をワークスペースとして開く - 指定された拡張機能をインストール 28
カスタマイズ: ワークスペースをルートにしたい 場合 パターン2 をベースに、ワークスペースだけルートにすることも可能 { "workspaceFolder": "/app", // ルートを開く
"service": "frontend" // 接続先は frontend コンテナ } これにより: ファイルツリーには全ファイルが表示 拡張機能は frontend 用のみインストール Git 操作もコンテナ内で可能 29
まとめ パターン1(単一)がおすすめ 1人開発 少人数で全体を触る 同じ言語スタック パターン2(サービス別)がおすすめ チーム開発 担当が分かれている 言語が大きく異なる 正解は1つではない。チームとプロジェクトに合わせて選択する
30
ありがとうございました