はじめに
MacでOllamaの環境構築方法を紹介する。Macのコンテナ上でGPUを利用することは可能であるが、現状はPodman以外の選択肢がなく設定に手間がかかるため(詳細は付録を参照)、今回は、Homebrewを使って仮想環境ではなく直接Mac本体にOllamaをインストールする方法を紹介する。
動作確認環境
- Macbook Pro (M4)
- macOS Sequoia 15.6
- Homebrew
方法
事前準備
Homebrewをインストールする。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Ollamaの環境構築
インストール
brew install ollama
HomebrewではCUI版とGUI版は分かれている。今回は、CUI版を対象とする。GUI版は以下となる。
-
ollama-app
brew install --cask ollama-app
Homebrewサービスを利用したOllamaの起動方法
再起動時にもOllamaを自動起動するように、HomebrewのサービスとしてOllamaを起動する。Ollamaの設定を変更しない場合は、以下のコマンドでサービス設定可能である。
brew services start ollama
しかし、上記のコマンドでOllamaをHomebrewのサービスとして起動すると、ターミナルに表示されているOllamaの環境変数の設定が反映されない(例:issue3581)。
そこで、以下のOllamaの環境変数を.env
ファイルから設定できるスクリプトを作成した。
以下にこのスクリプトの利用方法を紹介する。このプロジェクトを任意のワークスペースにクローンして利用する。
git clone https://github.com/ntrlmt/ollama-brew-service-setup.git
cd ollama-brew-service-setup
環境変数の変更
Ollamaは環境変数で設定を変更できる。GPUリソースが少ない環境での環境変数の設定を以下の記事に以前記載した。
環境変数は、上記のプロジェクトフォルダ(ollama-brew-service-setup)内の.env
ファイルに記載する仕様とした。.env.example
ファイルを用意したのでコピーして利用することができる。
cp .env.example .env
適宜、環境変数の値を自身の環境に合わせて修正する。#
を先頭につけると無視され、Ollamaのデフォルト値が利用される設定となる。
開始
./scripts/start-ollama-brew-service.sh
以下のようなログが出ればOllamaを開始できている。
Update plist and start Ollama service with brew.
Copied plist template to /Users/{username}/Library/LaunchAgents/homebrew.mxcl.ollama.plist
Updating environment variables in /Users/{username}/Library/LaunchAgents/homebrew.mxcl.ollama.plist from /Users/{username}/Documents/GitHub/ollama-brew-service-setup/.env...
Successfully updated environment variables in /Users/{username}/Library/LaunchAgents/homebrew.mxcl.ollama.plist
==> Successfully started `ollama` (label: homebrew.mxcl.ollama)
ログの確認
./scripts/log-ollama-brew-service.sh
以下のようなログが出れば成功。msg="server config" env="map[...]
で設定した環境変数が表示されていることが確認できる。
[GIN] 2025/09/16 - 22:01:24 | 200 | 8.941417ms | 127.0.0.1 | GET "/api/tags"
time=2025-09-16T22:01:47.806+09:00 level=INFO source=routes.go:1332 msg="server config" env="map[HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_CONTEXT_LENGTH:4096 OLLAMA_DEBUG:INFO OLLAMA_FLASH_ATTENTION:true OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://0.0.0.0:11434 OLLAMA_KEEP_ALIVE:5m0s OLLAMA_KV_CACHE_TYPE:q8_0 OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:1 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:/Users/{username}/.ollama/models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NEW_ENGINE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:1 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://* vscode-file://*] OLLAMA_SCHED_SPREAD:false http_proxy: https_proxy: no_proxy:]"
time=2025-09-16T22:01:47.807+09:00 level=INFO source=images.go:477 msg="total blobs: 5"
time=2025-09-16T22:01:47.807+09:00 level=INFO source=images.go:484 msg="total unused blobs removed: 0"
time=2025-09-16T22:01:47.807+09:00 level=INFO source=routes.go:1385 msg="Listening on [::]:11434 (version 0.11.11)"
time=2025-09-16T22:01:47.824+09:00 level=INFO source=types.go:131 msg="inference compute" id=0 library=metal variant="" compute="" driver=0.0 name="" total="16.0 GiB" available="16.0 GiB"
time=2025-09-16T22:01:47.824+09:00 level=INFO source=routes.go:1426 msg="entering low vram mode" "total vram"="16.0 GiB" threshold="20.0 GiB"
[GIN] 2025/09/16 - 22:02:14 | 200 | 2.777208ms | 127.0.0.1 | GET "/api/tags"
動作確認
適当なモデルで動作確認する。今回は、軽量なモデルであるGemma3:270mで動作確認した。
ollama run gemma3:270m
>>> こんにちは
こんにちは!何かお手伝いできることはありますか? 😊
Ollama起動中にログを確認すると、環境変数で設定した値が使われていることが確認できる。
./scripts/log-ollama-brew-service.sh
time=2025-09-16T21:52:58.349+09:00 level=INFO source=server.go:217 msg="enabling flash attention"
time=2025-09-16T21:52:58.349+09:00 level=INFO source=server.go:399 msg="starting runner" cmd="/opt/homebrew/Cellar/ollama/0.11.11/bin/ollama runner --ollama-engine --model /Users/{username}/.ollama/models/blobs/sha256-735af2139dc652bf01112746474883d79a52fa1c19038265d363e3d42556f7a2 --port 50995"
time=2025-09-16T21:52:58.350+09:00 level=INFO source=server.go:672 msg="loading model" "model layers"=19 requested=-1
time=2025-09-16T21:52:58.350+09:00 level=INFO source=server.go:678 msg="system memory" total="24.0 GiB" free="7.8 GiB" free_swap="0 B"
time=2025-09-16T21:52:58.350+09:00 level=INFO source=server.go:686 msg="gpu memory" id=0 available="15.5 GiB" free="16.0 GiB" minimum="512.0 MiB" overhead="0 B"
time=2025-09-16T21:52:58.360+09:00 level=INFO source=runner.go:1254 msg="starting ollama engine"
time=2025-09-16T21:52:58.360+09:00 level=INFO source=runner.go:1289 msg="Server listening on 127.0.0.1:50995"
time=2025-09-16T21:52:58.361+09:00 level=INFO source=runner.go:1173 msg=load request="{Operation:fit LoraPath:[] Parallel:1 BatchSize:512 FlashAttention:true KvSize:4096 KvCacheType:q8_0 NumThreads:4 GPULayers:19[ID:0 Layers:19(0..18)] MultiUserCache:false ProjectorPath: MainGPU:0 UseMmap:false}"
time=2025-09-16T21:52:58.376+09:00 level=INFO source=ggml.go:131 msg="" architecture=gemma3 file_type=Q8_0 name="" description="" num_tensors=236 num_key_values=37
time=2025-09-16T21:52:58.376+09:00 level=INFO source=ggml.go:104 msg=system Metal.0.EMBED_LIBRARY=1 Metal.0.BF16=1 CPU.0.NEON=1 CPU.0.ARM_FMA=1 CPU.0.FP16_VA=1 CPU.0.DOTPROD=1 CPU.0.LLAMAFILE=1 CPU.0.ACCELERATE=1 compiler=cgo(clang)
ggml_metal_init: allocating
ggml_metal_init: picking default device: Apple M4
ggml_metal_load_library: using embedded metal library
ggml_metal_init: GPU name: Apple M4
ggml_metal_init: GPU family: MTLGPUFamilyApple9 (1009)
ggml_metal_init: GPU family: MTLGPUFamilyCommon3 (3003)
ggml_metal_init: GPU family: MTLGPUFamilyMetal3 (5001)
ggml_metal_init: simdgroup reduction = true
ggml_metal_init: simdgroup matrix mul. = true
ggml_metal_init: has residency sets = true
ggml_metal_init: has bfloat = true
ggml_metal_init: use bfloat = true
ggml_metal_init: hasUnifiedMemory = true
ggml_metal_init: recommendedMaxWorkingSetSize = 17179.89 MB
time=2025-09-16T21:53:09.985+09:00 level=INFO source=runner.go:1173 msg=load request="{Operation:alloc LoraPath:[] Parallel:1 BatchSize:512 FlashAttention:true KvSize:4096 KvCacheType:q8_0 NumThreads:4 GPULayers:19[ID:0 Layers:19(0..18)] MultiUserCache:false ProjectorPath: MainGPU:0 UseMmap:false}"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=runner.go:1173 msg=load request="{Operation:commit LoraPath:[] Parallel:1 BatchSize:512 FlashAttention:true KvSize:4096 KvCacheType:q8_0 NumThreads:4 GPULayers:19[ID:0 Layers:19(0..18)] MultiUserCache:false ProjectorPath: MainGPU:0 UseMmap:false}"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=ggml.go:487 msg="offloading 18 repeating layers to GPU"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=ggml.go:493 msg="offloading output layer to GPU"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=ggml.go:498 msg="offloaded 19/19 layers to GPU"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:310 msg="model weights" device=Metal size="271.8 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:315 msg="model weights" device=CPU size="170.0 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:321 msg="kv cache" device=Metal size="14.3 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:332 msg="compute graph" device=Metal size="17.5 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:337 msg="compute graph" device=CPU size="1.2 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=backend.go:342 msg="total memory" size="474.9 MiB"
time=2025-09-16T21:53:10.118+09:00 level=INFO source=sched.go:473 msg="loaded runners" count=1
time=2025-09-16T21:53:10.118+09:00 level=INFO source=server.go:1251 msg="waiting for llama runner to start responding"
time=2025-09-16T21:53:10.120+09:00 level=INFO source=server.go:1285 msg="waiting for server to become available" status="llm server loading model"
time=2025-09-16T21:53:10.371+09:00 level=INFO source=server.go:1289 msg="llama runner started in 12.02 seconds"
[GIN] 2025/09/16 - 21:53:10 | 200 | 12.106945584s | 127.0.0.1 | POST "/api/generate"
終了
終了するときは、以下のコマンドを実行する。
./scripts/stop-ollama-brew-service.sh
以下のような表示が出れば、正常に終了できている。
Stop Ollama service with brew.
Stopping `ollama`... (might take a while)
==> Successfully stopped `ollama` (label: homebrew.mxcl.ollama)
【参考】各スクリプトの解説
サービス定義ファイル修正スクリプト: update-ollama-brew-plist-env-vars.sh
Homebrewでサービスとして登録する際の設定方法について紹介する。Homebrewは、~/Library/LaunchAgentsにサービスの定義ファイルが自動的に作成される。Ollamaをサービスとして起動すると以下のplistファイル(homebrew.mxcl.ollama.plist)が自動的に作成される。この設定ファイルにOllamaの環境変数を設定するスクリプトを作成する。
<?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>EnvironmentVariables</key>
<dict>
<key>OLLAMA_FLASH_ATTENTION</key>
<string>1</string>
<key>OLLAMA_KV_CACHE_TYPE</key>
<string>q8_0</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>homebrew.mxcl.ollama</string>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
<string>Background</string>
<string>LoginWindow</string>
<string>StandardIO</string>
<string>System</string>
</array>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/opt/ollama/bin/ollama</string>
<string>serve</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/opt/homebrew/var/log/ollama.log</string>
<key>StandardOutPath</key>
<string>/opt/homebrew/var/log/ollama.log</string>
<key>WorkingDirectory</key>
<string>/opt/homebrew/var</string>
</dict>
</plist>
上記のサービス定義ファイルに、環境変数の設定を追加するスクリプトを以下のように作成した。このスクリプトでは、.env
ファイルに記載の環境変数名(キー)とその値(バリュー)を読み込み、サービス定義ファイルに追記する。
上記スクリプトを実行すると以下のように、環境変数が追記される。<dict>
の下の階層に<dict>
が作成され、その中に環境変数が設定される。
<?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>EnvironmentVariables</key>
<dict>
<key>OLLAMA_CONTEXT_LENGTH</key>
<string>4096</string>
<key>OLLAMA_FLASH_ATTENTION</key>
<string>1</string>
<key>OLLAMA_HOST</key>
<string>0.0.0.0:11434</string>
<key>OLLAMA_KV_CACHE_TYPE</key>
<string>q8_0</string>
<key>OLLAMA_MAX_LOADED_MODELS</key>
<string>1</string>
<key>OLLAMA_NUM_PARALLEL</key>
<string>1</string>
<key>OLLAMA_SCHED_SPREAD</key>
<string>0</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>homebrew.mxcl.ollama</string>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
<string>Background</string>
<string>LoginWindow</string>
<string>StandardIO</string>
<string>System</string>
</array>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/opt/ollama/bin/ollama</string>
<string>serve</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/opt/homebrew/var/log/ollama.log</string>
<key>StandardOutPath</key>
<string>/opt/homebrew/var/log/ollama.log</string>
<key>WorkingDirectory</key>
<string>/opt/homebrew/var</string>
</dict>
</plist>
起動スクリプト: start-ollama-brew-service.sh
./scripts/update-ollama-brew-plist-env-vars.shを実行してサービス定義ファイルを更新し、そのサービス定義ファイルを指定して、Homebrewのサービスコマンドで、Ollamaのサービスを実行する。
終了スクリプト: stop-ollama-brew-service.sh
Homebrewのサービスコマンドで、Ollamaのサービスを停止する。
ログ確認スクリプト: log-ollama-brew-service.sh
HomebrewのOllamaサービスに関するログを表示する。
まとめ
Homebrewを使って仮想環境ではなく直接Mac本体にOllamaをインストールする方法を紹介した。Homebrewのサービスの機能を使って、Ollamaをサービスとして起動する方法を紹介した。合わせて、HomebrewのサービスでOllamaの環境変数の設定方法を紹介した。MacでOllamaを常駐させるときに便利なので試してほしい。
参考
付録
コンテナ内のGPUアクセスに関する情報
Podman + libkrun
Podman+libkrunを使うと、コンテナ内でGPUを利用できる模様。
Apple純正ツール「container」
AppleはOSSでコンテナ実行用のツール「container」を発表した。しかし、まだGPUの対応はされていない模様。