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
410
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
TinyGo 開発サイクルを高速化する:Go で作るエミュレータ入門
zozotech
PRO
1
740
俺の仕事は AIに奪われないし、たぶんその BIも要らない
hikaruri
0
490
空間オーディオで過去の 自分(ゴースト)と競うランニング 〜HealthKitのルートを足音に変える実装〜
nao_randd
0
220
データ_AIの事業の勝敗をわけるもの
nek0128
0
370
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
820
GoにおけるFFIのこれまでとこれから
goccy
5
3.5k
あるけみー式LTスライド作成術
alchemy1115
1
210
SREは、MCPとAutopilotをこう使え!
kazumax55
2
810
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
190
The Agent Builder Loop from Daily Work to OSS
minorun365
PRO
3
200
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
22
14k
Featured
See All Featured
Ethics towards AI in product and experience design
skipperchong
2
370
The Spectacular Lies of Maps
axbom
PRO
1
990
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.8k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
520
How to Think Like a Performance Engineer
csswizardry
28
2.8k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
First, design no harm
axbom
PRO
2
1.3k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
230
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
460
The Language of Interfaces
destraynor
162
27k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
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
ありがとうございました