Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
モノレポ × DevContainere 設計パターン
Search
abimaru
December 19, 2025
Technology
190
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
370
Other Decks in Technology
See All in Technology
AIのReact習熟度を測る
uhyo
2
660
IaC コードを資産へ:AWS CDK 社内ライブラリと横断展開 / aws-summit-japan-2026
gotok365
7
1.3k
不要なレビューをAIにまかせて AIコーディングの環境改善を加速した
shoota
1
230
いまさら聞けない「仕様駆動開発入門」 〜AI活用時代の開発プロセスを考える〜
findy_eventslides
2
160
あなたの知らないPDFのアクセシビリティ
lycorptech_jp
PRO
0
220
【Cyber-sec+】経営層を"動かす"ための考え方
hssh2_bin
0
200
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
2k
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
470
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
3k
2026年6月23日 Syncable Tech + Start Python Club にて
hamukazu
0
140
Kiroで書いた 設計書 が AI レビューの 採点基準 になる
ezaki
0
130
【Snowflake Summit 2026 Recap!!】Snowflake Summit Deep Dive: Security & Governance
civitaspo
1
270
Featured
See All Featured
Exploring anti-patterns in Rails
aemeredith
3
410
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
330
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
1
200
How to make the Groovebox
asonas
2
2.2k
The agentic SEO stack - context over prompts
schlessera
0
820
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Un-Boring Meetings
codingconduct
0
320
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
850
Producing Creativity
orderedlist
PRO
348
40k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
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
ありがとうございました