ガイド/Dockerのメモリ使用量が多すぎる
MacでDockerのメモリ使用量が多すぎる? 原因のコンテナの見つけ方と上限の設定
結論
Macでは、Dockerはすべてのコンテナを1つのLinux仮想マシンの中で動かすので、アクティビティモニタにはコンテナではなく、大きなプロセスが1つ(たいていはVirtual Machine Service for Docker)表示されます。どのコンテナがメモリを使っているかを見るには、docker statsを実行します。合計に上限を設定するには、Docker DesktopのSettings → Resources → Advancedで“Memory limit”を下げます。デフォルトはMacのメモリの半分です。同じ場所にある“Resource Saver”は、Docker Desktopがアイドル状態のときに仮想マシンをオフにします。Mac用システムモニタのVitalsなら、“コンテナ”タブで各コンテナのメモリ、CPU、ネットワーク、ポートを表示し、メニューバーからコンテナを停止できます。
Dockerのメモリを見つけて上限を設定する方法
- 01 アクティビティモニタを開いて“メモリ”をクリックし、検索フィールドに“Docker”と入力します。いちばん大きい行が、コンテナを動かしている仮想マシンです。AppleのVirtualizationフレームワークを使っている場合は、Virtual Machine Service for Dockerという名前です。com.docker.backendはDocker Desktop自体です。
- 02 ターミナルで
docker stats --no-streamを実行します。各行が実行中のコンテナで、MEM USAGE / LIMITに使用量と使用できる上限が表示されます。 - 03 使っていないものを停止します。
docker stopのあとにコンテナ名を付けるか、Composeプロジェクトのフォルダでdocker compose downを実行します。 - 04 Docker DesktopのSettings → Resources → Advancedを開き、“Memory limit”を、最も忙しいときに
docker statsが示す値より少し上まで下げます。変更を適用すると、Docker Desktopが仮想マシンを再起動します。 - 05 同じセクションで“Resource Saver”をオンにして、コンテナが1つも動いていない間は仮想マシンがシャットダウンするようにします。
OrbStack、Colima、Rancher Desktop、Podmanもコンテナを仮想マシンの中で動かし、それぞれ独自のメモリ設定があります。Colimaなら、colima start --memory 4で仮想マシンに4 GBを割り当てます。
コンテナはLinuxの機能なので、Macではどのエンジンも小さなLinux仮想マシンの中でコンテナを動かします。macOSにはその仮想マシンが1つのプロセスにしか見えず、中のどのコンテナが何を使っているかはわかりません。アクティビティモニタに数GBのプロセスが1つだけ表示され、コンテナがまったく表示されないのはそのためで、答えがDocker自身のツールにあるのもそのためです。下の表では、見えているものが何で、どうすればよいかを示しています。
Dockerのメモリの行き先
| 見えているもの | 概要 | すること |
|---|---|---|
| Virtual Machine Service for Dockerが数GB | すべてのコンテナを動かしているLinux仮想マシン | Settings → Resources → Advancedで“Memory limit”を下げる |
| com.docker.backend | Docker Desktop自体のプロセス | たいていは小さい。増え続けるならDocker Desktopを再起動 |
| コンテナが動いていないのにメモリ使用量が高いまま | 仮想マシンが使ったメモリを抱えたまま | “Resource Saver”をオンにするか、Docker Desktopを終了 |
| 上限に近いコンテナがある | メモリが足りないか、メモリリークしている | docker statsと、コンテナごとの上限 |
| イメージのビルド中にメモリ使用量が増える | ビルドは同じ仮想マシンで実行される | 普通のこと。ビルドが終われば下がる |
アクティビティモニタにDockerの大きなプロセスが1つだけ表示される理由
仮想マシンは、ほかのアプリと同じようにmacOSからメモリを受け取ります。上限は設定した“Memory limit”までです。その中ではLinuxがメモリをコンテナに分け、残りはmacOSと同じようにファイルのキャッシュに使います。外から見ると、すべて同じに見えます。大量のメモリを抱えた1つのプロセスです。
内訳を知っているのはエンジンだけで、docker statsはそれをエンジンに尋ねるコマンドです。そこでのCPU %の列は仮想マシンのCPUに対する割合で、MEM %はコンテナの上限(上限がなければ仮想マシン全体)に対する割合です。
Dockerに割り当てるメモリの量
Docker Desktopは、デフォルトでMacのメモリの半分を使います。16 GBのMacなら8 GBです。アプリサーバ、データベース、キャッシュといった一般的な開発環境なら、たいていずっと少なくて済みます。いつもどおりに環境を動かし、最も忙しいときのdocker statsの合計を見て、“Memory limit”をそれより少し上に設定しましょう。
低くしすぎると、仮想マシン内のLinuxがメモリ不足になったコンテナを停止します。docker inspect --format '{{.State.OOMKilled}}'のあとにコンテナ名を付けて実行すると、そうなった場合はtrueと表示されます。上限を上げるか、そのコンテナに個別の上限を設定して、ほかのコンテナを巻き込まないようにしましょう。
コンテナごとにメモリの上限を設定する
コンテナ1つに上限を設定すれば、メモリリークのあるサービスが仮想マシンを埋め尽くすのを防げます。docker runなら、--memory 512mを追加します。Composeファイルでは、サービスにmem_limit: 512mを設定します。上限を超えるとコンテナは停止され、docker statsでは使用量の横に上限が表示されます。
Dockerがメモリを返さない理由
コンテナを停止すると仮想マシン内のメモリは解放されますが、仮想マシンがそれをすぐにmacOSに返すとは限らないので、アクティビティモニタの数値は高いままのことがあります。“Resource Saver”は、Docker Desktopがアイドル状態のときに仮想マシンをオフにしてすべてを返し、コンテナが必要になれば数秒で再び起動します。Docker Desktopを終了しても同じです。
Dockerとディスク容量
イメージ、停止したコンテナ、ボリューム、ビルドキャッシュは、作業につれて大きくなる1つのディスクイメージに保存され、Macではシステムデータに含まれます。docker system dfで種類ごとの使用量がわかります。docker system pruneは、停止したコンテナ、未使用のネットワーク、どこからも参照されていないイメージ、ビルドキャッシュを削除します。--volumesは、必要なデータがボリュームにないと確信できる場合にだけ追加してください。Docker Desktopの設定で“Memory limit”の隣にある“Disk usage limit”で上限を設定できます。
Vitalsでできること
Vitalsは、仮想マシンがmacOSに教えない、各コンテナのメモリを表示します。
- “コンテナ”タブで、すべてのコンテナのメモリ、CPU、ネットワーク、ディスク、公開ポートを表示。Composeプロジェクトはまとめて表示
- 最大のコンテナと上限に最も近いコンテナのカード、コンテナ別メモリのグラフ
- Docker Desktopは仮想マシンを含めてアプリのリストに1行で表示。クリックすると中のコンテナを表示
- メニューバーのドロップダウンにもコンテナを表示し、確認のうえワンクリックで停止。Dockerコンテナを停止する方法を参照
- Docker Desktop、OrbStack、Colima、Rancher Desktop、Podmanに対応
知っておくと便利なこと
- Vitalsはエンジンからコンテナの数値を読み取るだけで、コンテナを起動したり削除したりすることはありません。行う変更は停止だけで、それもあなたが指示したときだけです。
- このタブは、エンジンが動いている間だけ表示されます。
よくある質問
MacでDockerのメモリ使用量が多いのはなぜ?
DockerはコンテナをLinux仮想マシンで動かし、その仮想マシンは“Memory limit”(デフォルトはMacのメモリの半分)まで使います。Settings → Resources → Advancedで“Memory limit”を下げ、docker statsを実行して、どのコンテナが最も使っているかを確認しましょう。
Virtual Machine Service for Dockerとは?
AppleのVirtualizationフレームワークを使う場合に、Docker Desktopがコンテナを動かす仮想マシンです。そのメモリは、中のコンテナとLinuxが使うすべてで、上限はDocker Desktopの“Memory limit”です。
MacでDockerのメモリを制限するには?
Docker DesktopでSettings → Resources → Advancedを開き、“Memory limit”を下げます。コンテナ1つなら、docker run --memory 512mを使うか、Composeファイルでmem_limit: 512mを使います。
コンテナを停止してもDockerがメモリを返さないのはなぜ?
仮想マシンは、コンテナが停止したあとも、使ったメモリの一部を抱えたままにします。Docker Desktopがアイドル状態のときに仮想マシンをオフにする“Resource Saver”をオンにするか、Docker Desktopを終了しましょう。
Virtual Machine Service for DockerのCPU使用率が高いのはなぜ?
たいていはコンテナが忙しいからで、docker statsでどれかがわかります。コンテナが動いていないのにCPU使用率が高いままなら、Docker Desktopを終了して開き直し、アップデートしましょう。何も動いていないのにCPU使用率が高くなる問題は、一部のDocker Desktopのバージョンでバグとして報告されています。
MacでDockerにどれくらいメモリを割り当てるべき?
コンテナが最も忙しいときに使う量(docker statsで確認できます)より少し多めにします。一般的な開発環境なら2〜4 GBで足りることが多く、デフォルトのMacのメモリの半分を大きく下回ります。
MacでDockerコンテナのメモリがわかるアプリはある?
Vitalsの“コンテナ”タブでは、Docker Desktop、OrbStack、Colima、Rancher Desktop、Podmanについて、各コンテナのメモリ、CPU、ネットワーク、ディスク、ポートを表示します。確認のうえ、メニューバーからコンテナを停止することもできます。