Mac mini を AI 開発拠点として最適化する完全ガイド 2026

Mac mini を AI 開発拠点として最適化する完全ガイド 2026

M2 Pro / M4 Pro / M4 Max の選定から OrbStack・Ollama・Claude Code の同居構成、LaunchAgent で 24 時間稼働させるチューニングまで。Mac mini を AI 開発拠点として使い倒す実践ガイド。

エンジニアのゆとです。

Mac mini を AI 開発の据え置き拠点にしてから、ラップトップへの依存がだいぶ薄れた。

Claude Code を走らせながら、OrbStack で複数コンテナを回して、Ollama で Llama 3 をローカル推論させる。全部同時。ラップトップだとファンが唸り始めるやつを、Mac mini は静かにこなす。

この記事は「Mac mini に乗り換えるかどうか」の話じゃない。もう持っている(あるいは買うと決めた)前提で、どう構成して何をチューニングすれば AI 開発拠点として最大限に機能するか、という実践ガイド。

M チップ別のハードウェア選定、OS 設定、OrbStack + Docker + Ollama + Claude Code の同居構成、LaunchAgent で 24 時間稼働させるための電源管理まで一通り書く。

なお Docker Desktop を OrbStack に乗り換える話は別記事で書いた。

Docker Desktopのメモリ食いすぎ問題にMacエンジニアが終止符を打った話
Docker Desktopのメモリ食いすぎ問題にMacエンジニアが終止符を打った話OrbStackの存在は知ってた。知ってたけど乗り換えが面倒で放置してた。重い腰を上げて実際に計測したら差がエグかったので全部書く。読む →

なぜ Mac mini が AI 開発に向いてるのか

Apple Silicon のメモリアーキテクチャが効く

M チップで最も重要なのはメモリ統合アーキテクチャ(Unified Memory)。CPU と GPU が同じメモリプールを共有するので、LLM のローカル推論で「GPU に VRAM が足りない」問題が原理的に起きない。

NVIDIA GPU + 通常 RAM 構成だと、モデルのウェイトを VRAM に乗せる必要がある。RTX 3090 の 24GB VRAM に収まらないモデルは CPU に分散させてボトルネックになる。Apple Silicon は 96GB の統合メモリを GPU も CPU も透過的に使うので、Llama 3 70B(約 40GB)でも詰まらずに推論できる。

実測でいうと、M4 Max 96GB 環境で Ollama + llama3.3:70b を走らせると、70B クラスが ~15 tokens/sec 前後で出る。CPU オフロード含む他のアーキテクチャと比べてかなり現実的な速度。

消費電力と静音性

Mac mini M4 Pro の TDP は 30W 前後(フルロード時で 60W 程度)。Geekbench や実測ベースだと、Claude Code + OrbStack + Ollama 同時稼働でもファンがほぼ聞こえない。24 時間稼働させても月の電気代は数百円レベル。

デスクトップ AI ワークステーション(RTX 4090 搭載 PC)だと TDP が 450W を超えるモデルもある。同じ推論タスクを比較するのは単純じゃないけど、「静かに、安く、常時動く」という用途では Mac mini に分がある。

macOS エコシステムとの親和性

Apple Silicon 最適化済みの Metal バックエンドを Ollama が使うので、わざわざ CUDA を組む必要がない。Homebrew、Xcode CLI、Node.js、Python 全部そのまま動く。iOS / macOS アプリ開発とのクロスプラットフォーム開発環境も一台で完結する。


ハードウェア選定

M チップ別の選び方

用途推奨モデル理由
CC + Docker + 7B〜13B OllamaM4 Pro 24GB14コアCPU + 30コアGPU、バランス型。7B は 2〜3 token/sec で余裕、13B でも実用域
CC + 複数コンテナ + 30B〜70B OllamaM4 Pro 48GB70B モデルが推論できるメモリ下限。フル活用するならここから
本格 AI 推論 + 100B クラスM4 Max 64GB / 128GB推論速度が別次元。Mac Studio と迷うラインだけど mini の方が安い
予算優先 / 軽量用途M2 Pro 16GBOllama は 7B 止まり。CC + Docker は余裕。ただしメモリ圧迫は起きる

M2 Pro 16GB は正直、AI 開発拠点として使うには手狭になってきている。Claude Code がコンテキストを大量に積む使い方をすると、Ollama まで一緒に走らせるとメモリがコンプレッションフルになる。

16GB で AI を使うなら、Ollama は割り切って「軽量モデル専用」にするか、クラウド API に逃がす前提で持つべき。

新規購入なら M4 Pro 24GB を最低ラインとして考えたい。48GB まで積むと 70B クラスの Qwen・Llama が日常ツールになる。

メモリは後から増やせない(重要)

Apple Silicon は CPU もメモリも GPU もワンチップ。購入時に選んだメモリ容量が固定。「あとでメモリを増やす」は不可能。

これが Mac mini 選定で一番重要な点。悩むなら多い方を買う。後悔するのは常に「もうちょっと積んでおけば」の方向だから。

外付け SSD

内蔵 SSD は高速(M4 系で 7GB/s 前後)だけど、AI モデルのウェイトは重い。Llama 3 70B だけで 40GB 超。複数モデルを手元に置くと内蔵だけでは足りなくなる。

Ollama のモデルディレクトリを外付け SSD に向ける構成が現実的。

# ~/.ollama/models を外付けSSDに移す
mkdir -p /Volumes/MySSD/ollama-models
ln -s /Volumes/MySSD/ollama-models ~/.ollama/models

Thunderbolt 4 接続の SSD(Samsung T9 や Crucial X9 Pro)なら読み書き 1,000MB/s 前後出る。USB4 対応モデルなら 2,000MB/s 超も。モデルロード時間は体感できるくらい違う。


OS・開発環境の最適化

macOS 設定

AI 開発拠点として 24 時間稼働させるなら、まず不要な OS のリソース消費を削る。

# スポットライトのインデックス対象を絞る(AI モデルファイルはインデックス不要)
sudo mdutil -i off /Volumes/MySSD

# Time Machine の除外設定(モデルファイルをバックアップ対象外に)
sudo tmutil addexclusion ~/.ollama/models

スクリーンセーバーと自動スリープはシステム設定から切る(後述の電源管理でも設定するけど、UI からも確実にオフにしておく)。

OrbStack

Docker Desktop の代替として OrbStack を使う。メモリ消費が圧倒的に少ない。

brew install orbstack

起動したら Docker Desktop をアンインストール。既存の docker-compose.yml はそのまま動く。OrbStack は Docker Engine 互換 API を提供しているので、docker コマンドも docker compose もそのまま使える。

OrbStack の詳細なメモリ計測データは docker-mac-memory-solution の記事に書いているので参照してほしい。

Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# PATH を fish / zsh に追加(Apple Silicon は /opt/homebrew)
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc

Intel Mac と Apple Silicon で Homebrew のインストールパスが違う(Intel は /usr/local、Apple Silicon は /opt/homebrew)。どちらが入っているか確認してから PATH を設定する。

which brew
# Apple Silicon なら /opt/homebrew/bin/brew が返る

Xcode CLI Tools

xcode-select --install

これを入れないと Git や Make が動かない。Xcode フルパッケージは不要(ストレージを 10GB 以上食うので CLI だけで十分)。

Python 環境

システム Python(/usr/bin/python3)は macOS 管理なので直接触らない。仮想環境ごとに分離する。

brew install pyenv
pyenv install 3.12.0
pyenv global 3.12.0

# プロジェクトごとに venv を作る
python3 -m venv .venv
source .venv/bin/activate

Ollama の Python クライアントや LangChain を入れるなら、プロジェクトごとに venv を切る運用が安全。全部グローバルに積むとバージョン競合で詰まる。

メモリ管理(compressed memory と swap)

Apple Silicon の macOS はメモリが埋まると自動でコンプレッションを始める。アクティビティモニタの「メモリ圧力」が緑なら余裕、黄色は圧縮が進んでいる状態、赤は swap が発生している。

Ollama + Claude Code + OrbStack 同時稼働時の目安:

  • 24GB 機: 黄色になることが多い。70B モデルを走らせると赤になる
  • 48GB 機: 70B でも緑〜黄色で収まることが多い
  • 16GB 機: 重めの 7B でも黄色、13B で赤

swap が発生すると SSD を頻繁に読み書きするので、内蔵 SSD の寿命にも影響する。16GB 機で無理に 13B を動かし続けるのは避けた方がいい。

# 現在のメモリ圧力確認
memory_pressure

# swap 使用量確認
sysctl vm.swapusage

CC + Docker + Ollama の同居構成

ディレクトリ構成

~/
├── Project/
│   ├── project-a/          # 各プロジェクト
│   │   ├── .venv/
│   │   ├── docker-compose.yml
│   │   └── CLAUDE.md
│   └── project-b/
├── .ollama/
│   └── models -> /Volumes/MySSD/ollama-models  # シンリンク
└── .config/
    └── claude/

Ollama のインストールと設定

brew install ollama

# サービスとして登録(再起動後も自動起動)
brew services start ollama

# モデル取得
ollama pull llama3.3:70b        # 40GB、70B クラス
ollama pull qwen2.5-coder:32b   # 20GB、コーディング特化
ollama pull nomic-embed-text    # 274MB、埋め込みモデル

Ollama はデフォルトで localhost:11434 で API を提供する。OLLAMA_HOST 環境変数を設定すれば LAN 内の他のデバイスからもアクセスできる。

# LAN に公開したい場合(~/.zshrc or LaunchAgent の EnvironmentVariables に設定)
export OLLAMA_HOST=0.0.0.0:11434

ただし LAN 公開する場合は認証がないので、信頼できるネットワーク前提で。

Claude Code との同居

Claude Code(CC)は ~/.claude/ 配下に設定を持ち、プロジェクトごとに CLAUDE.md で動作をカスタマイズできる。Ollama との組み合わせは今のところ CC 自身がローカル LLM を使うわけじゃなく、CC が作業する中で「Ollama を呼ぶスクリプトを実行する」形になる。

典型的なパターン:

# CLAUDE.md でローカルモデルの用途を指定しておく
# 例: テスト自動修正は CC、コード説明文の生成は Ollama で高速化

CC を走らせながら Ollama で推論するとメモリを両方が使う。前述の通り 24GB 機だと圧迫感が出る。48GB 以上なら余裕を持って同居できる。

Docker Compose の典型構成

AI 開発でよく使うコンテナ構成:

# docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: devpass
    volumes:
      - pg_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  qdrant:
    image: qdrant/qdrant:latest
    ports:
      - "6333:6333"
    volumes:
      - qdrant_data:/qdrant/storage

volumes:
  pg_data:
  qdrant_data:

Qdrant はベクターDBで、Ollama の埋め込みモデル(nomic-embed-text)と組み合わせてローカル RAG を構成する時に使う。全部 localhost で完結するので API キーも不要。

OrbStack 上でこの構成を走らせた時のリソース消費(M4 Pro 24GB 環境):

  • OrbStack VM: ~400MB
  • postgres: ~30MB
  • redis: ~5MB
  • qdrant: ~150MB
  • 合計コンテナ: ~600MB 前後

Docker Desktop だと OrbStack VM の代わりに LinuxKit VM が ~2GB 以上を確保する。この差が効いてくる。


リモートアクセス

SSH

Mac mini をヘッドレス(モニターなし)で使う場合、SSH が基本のアクセス手段。

# Mac mini 側: システム設定 > 一般 > 共有 > リモートログインをオン
# クライアント側
ssh username@macmini.local

# ポート転送で Ollama API にアクセス(Mac mini から外部へ持ち出す場合)
ssh -L 11434:localhost:11434 username@macmini.local

macmini.local は mDNS(Bonjour)による名前解決。同じ LAN なら IP アドレスの代わりに使える。

Tailscale

LAN 外(外出先や別拠点)から Mac mini に安全にアクセスしたいなら Tailscale が一番楽。

brew install --cask tailscale
# メニューバーから Tailscale を起動してログイン

Tailscale は WireGuard ベースの VPN で、NAT 越えを自動で処理する。自宅の Mac mini に外出先のラップトップからアクセスする時、ルーターの設定を触る必要がない。

Tailscale ネットワーク内では macmini という名前で直接アクセスできる。

# Tailscale 経由で SSH
ssh username@macmini

# Tailscale 経由で Ollama API にアクセス(Mac mini 側で OLLAMA_HOST=0.0.0.0 が必要)
curl http://macmini:11434/api/generate -d '{"model":"llama3.3","prompt":"test"}'

クラウド GPU との連携

Ollama でカバーできないモデルサイズ(100B 超)や特定の推論タスクでは、クラウド GPU を一時的に使う。

Runpod や Lambda Labs はオンデマンドで GPU インスタンスを借りられる。Mac mini 上のコードから OLLAMA_BASE_URL 環境変数を切り替えるだけで、ローカル Ollama とクラウド Ollama API を透過的に使い分けられる。

import os
client_url = os.environ.get("OLLAMA_BASE_URL", "http://localhost:11434")

24 時間稼働のためのチューニング

電源管理

# スリープを無効化(永続設定)
sudo pmset -a sleep 0          # システムスリープなし
sudo pmset -a disksleep 0      # ディスクスリープなし
sudo pmset -a displaysleep 10  # ディスプレイだけ10分でオフ(ヘッドレスなら関係ない)
sudo pmset -a powernap 0       # Power Nap 無効(余計なバックグラウンド処理を減らす)
sudo pmset -a womp 1           # Wake on LAN を有効(LAN から起動できるようにしておく)

設定確認:

pmset -g

停電後の自動起動:

システム設定 > 一般 > 電源 > 電源が失われた後に自動的に再起動

これをオンにしておかないと停電復旧後に Mac mini が起動しない。

LaunchAgent でサービスを常駐させる

Homebrew services(brew services start ollama)は LaunchAgent を使っている。自分のカスタムスクリプトも同じように LaunchAgent として登録すると、再起動後も自動起動する。

例:自作の定期実行スクリプトを LaunchAgent で登録する。

<!-- ~/Library/LaunchAgents/com.yutolab.daily-collector.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.yutolab.daily-collector</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
        <string>/Users/username/scripts/daily_collector.py</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>4</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/Users/username/logs/daily-collector.out</string>
    <key>StandardErrorPath</key>
    <string>/Users/username/logs/daily-collector.err</string>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
    </dict>
</dict>
</plist>
# 登録
launchctl load ~/Library/LaunchAgents/com.yutolab.daily-collector.plist

# 確認
launchctl list | grep yutolab

# 即時実行(テスト)
launchctl start com.yutolab.daily-collector

LaunchAgent の KeepAlive オプションを入れるとプロセスが死んだ時に自動で再起動する。常駐デーモンに使う。

<key>KeepAlive</key>
<true/>

ただし KeepAlive にすると意図的に止める時は launchctl unload が必要。killstop だけでは自動復活する。

自動再起動の設定

週に 1 回くらい再起動を入れることでメモリのフラグメンテーションがリセットされる。

<!-- ~/Library/LaunchAgents/com.yutolab.weekly-reboot.plist -->
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.yutolab.weekly-reboot</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/sudo</string>
        <string>/sbin/reboot</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Weekday</key>
        <integer>0</integer>
        <key>Hour</key>
        <integer>4</integer>
        <key>Minute</key>
        <integer>30</integer>
    </dict>
</dict>
</plist>

sudo を LaunchAgent で使う場合は sudoers に追加が必要(NOPASSWD 設定)。セキュリティリスクを理解した上で設定する。


実測データ: CC + Docker + Ollama 同時稼働

M4 Pro 24GB 環境での計測値。

アイドル時(各サービス起動済み、作業なし)

プロセスRAM 使用
OrbStack VM~380MB
Ollama(モデルなし)~50MB
Claude Code(起動済み、待機中)~120MB
macOS + Finder + Safari等~3.5GB
合計~4.1GB

作業中(CC がコード生成中 + Ollama 7B 推論 + Docker 3コンテナ)

プロセスRAM 使用
OrbStack + コンテナ 3本~800MB
Ollama + llama3.2:7b ロード済み~5.0GB
Claude Code(コンテキスト積み中)~400MB
システム~3.5GB
合計~9.7GB

24GB 機で 9.7GB 使用なら余裕がある。ここに 13B モデルを加えると ~18GB になってくる。70B を回したい場合は 48GB がほぼ必須。

推論速度(Ollama、M4 Pro 24GB)

モデルtokens/sec
llama3.2:3b~65 tok/s
llama3.2:7b~38 tok/s
qwen2.5-coder:14b~18 tok/s
qwen2.5-coder:32b~8 tok/s
llama3.3:70bロード不可(メモリ不足)

32B クラスは動くが遅め。日常会話レベルの用途なら実用的、長い推論は待つ。70B は 48GB 機から。


ハマりどころ

Ollama がモデルをロードしたまま RAM を解放しない

Ollama はモデルをロードすると、デフォルトで 5 分間メモリに保持する。連続推論には便利だけど、他のプロセスにメモリを渡したい時に邪魔になる。

# モデルをアンロードする
ollama stop llama3.3

# 自動アンロードの時間を変更(環境変数で指定)
export OLLAMA_KEEP_ALIVE=0     # 推論後即アンロード
export OLLAMA_KEEP_ALIVE=30m   # 30分保持

メモリ圧迫を感じたら ollama ps で何がロードされているか確認する。

OrbStack が Rosetta なしで ARM イメージを要求する

Apple Silicon で x86 コンテナを使う場合、Rosetta 2 が必要になることがある。

# Rosetta をインストール
softwareupdate --install-rosetta --agree-to-license

OrbStack の設定から「Rosetta」を有効にすると x86 イメージが動く。ただし性能は落ちる(エミュレーション)。本番が x86 Linux でも、開発は ARM イメージを使う方が速い。

LaunchAgent が “Service could not initialize” で落ちる

PATH が通っていないのが原因のことが多い。Terminal で動くスクリプトが LaunchAgent から動かないのは、LaunchAgent が ~/.zshrc を読まないから。

<key>EnvironmentVariables</key>
<dict>
    <key>PATH</key>
    <string>/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    <key>HOME</key>
    <string>/Users/username</string>
</dict>

StandardOutPathStandardErrorPath のログを必ず設定しておく。エラーが出ても stdout/stderr がないと何が起きたか追えない。

CC のコンテキストがメモリを圧迫する

Claude Code は 1M コンテキストウィンドウを持つモデルで動いている。長いセッションを続けると、コンテキストを保持するためのメモリ消費が増える。16GB 機では顕著に影響が出ることがある。

# CC の使用メモリを確認
ps aux | grep claude

# 定期的にセッションを再起動して解放する

長い作業は定期的にセッションを切って再開する習慣をつけた方が、メモリの観点では安定する。

Tailscale と OrbStack のネットワーク競合

稀なケースだけど、Tailscale の MagicDNS と OrbStack のコンテナ DNS が衝突することがある。OrbStack のコンテナ名前解決(mycontainer.orb.local)が Tailscale の DNS よりも先に解決されるように設定が必要な場合がある。

症状が出た場合は OrbStack の設定からカスタム DNS を確認する。


まとめ

Mac mini を AI 開発拠点として構成する際のポイントを整理する。

ハードウェア選定:

  • 16GB は手狭。新規ならM4 Pro 24GB を最低ラインに
  • 70B クラスのローカル推論が必要なら 48GB 以上
  • モデルファイル置き場は外付け SSD(Thunderbolt 4)

ソフトウェア構成:

  • Docker Desktop ではなく OrbStack を使う(メモリが全然違う)
  • Ollama は Homebrew services で自動起動
  • Python 環境は venv で分離、システム Python を汚染しない

24時間稼働:

  • pmset でスリープを無効化
  • LaunchAgent で各種スクリプトを常駐管理
  • KeepAlive=true のサービスは launchctl unload で止める
  • 停電復旧の自動起動を必ず設定

リソース管理:

  • ollama ps で常にロードモデルを確認
  • メモリ圧力が赤になったら使わないモデルをアンロード
  • CC セッションは定期的に切り直す

Mac mini は「静かに、長く、安く」動かし続けられる。ラップトップの熱問題や電源管理を気にせず、ひたすら処理を任せられる拠点として機能する。AI 開発でローカル環境に寄せたい人には、ちょうどいい選択肢だと思ってる。

← 記事一覧に戻る