<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>App-Sandbox on Tarragon</title><link>https://tarrragon.github.io/blog/tags/app-sandbox/</link><description>Recent content in App-Sandbox on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sun, 05 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/app-sandbox/index.xml" rel="self" type="application/rss+xml"/><item><title>macOS App Sandbox 與 ~/Library/Containers 架構</title><link>https://tarrragon.github.io/blog/macos/macos_app_sandbox_container/</link><pubDate>Sun, 05 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/macos/macos_app_sandbox_container/</guid><description>&lt;p>&lt;code>~/Library/Containers&lt;/code> 是 macOS 沙箱（App Sandbox）機制的產物。每個啟用沙箱的 App 在這裡有一個獨立的目錄，作為該 App 的隔離環境。排查磁碟空間時，Containers 常是 &lt;code>~/Library&lt;/code> 裡最大的子目錄之一，理解它的結構才能判斷哪些佔用是可以清除的快取、哪些是動不得的使用者資料。&lt;/p>
&lt;h2 id="沙箱的設計目的">沙箱的設計目的&lt;/h2>
&lt;p>App Sandbox 限制每個 App 只能存取自己的資料，不能碰其他 App 或使用者的檔案。這個隔離不是建議性的——沙箱由作業系統核心強制執行，App 程式碼裡寫了讀取其他 App 目錄的路徑，系統會拒絕。&lt;/p>
&lt;p>Mac App Store 上架的 App 必須啟用沙箱。非 App Store 分發的 App 可以選擇不啟用，但越來越多開發者主動啟用以獲得使用者信任。&lt;/p>
&lt;p>每個沙箱 App 拿到的是一個完整的家目錄副本——裡面有 &lt;code>Documents&lt;/code>、&lt;code>Library&lt;/code>、&lt;code>Downloads&lt;/code> 等跟使用者家目錄一樣的子目錄，但 App 看到的路徑是自己的副本，不是使用者真正的家目錄。這些副本就放在 &lt;code>~/Library/Containers/&amp;lt;bundle-id&amp;gt;/Data/&lt;/code> 下。&lt;/p>
&lt;h2 id="container-的內部結構">Container 的內部結構&lt;/h2>
&lt;p>每個 Container 的結構是固定的：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">~/Library/Containers/&amp;lt;bundle-id&amp;gt;/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">├── .com.apple.containermanagerd.metadata.plist # 容器 metadata
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">└── Data/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ├── Documents/ # App 的文件（使用者資料）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> ├── Library/ # App 的 Library（設定、快取、資料庫）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> │ ├── Caches/ # 快取（可安全清除）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> │ ├── Preferences/# 設定
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> │ └── ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ├── Downloads/ # 有的是 symlink 到使用者的 ~/Downloads
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> ├── Desktop/ # 通常是 symlink
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> ├── tmp/ # 暫存
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> └── StoreKit/ # App Store 相關&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Downloads&lt;/code>、&lt;code>Desktop&lt;/code>、&lt;code>Movies&lt;/code>、&lt;code>Music&lt;/code>、&lt;code>Pictures&lt;/code> 多數是 symlink（符號連結）指向使用者的對應目錄——沙箱允許 App 透過使用者授權存取這些位置。&lt;code>du&lt;/code> 加 &lt;code>-x&lt;/code> 旗標時不會跨越 symlink 計入，所以不會重複計算。&lt;/p>
&lt;h2 id="命名慣例bundle-id-vs-uuid">命名慣例：bundle ID vs UUID&lt;/h2>
&lt;p>Container 目錄的命名方式取決於 App 的來源。&lt;/p>
&lt;p>&lt;strong>Bundle ID&lt;/strong>（App 的唯一識別碼，格式為反向域名，例如 &lt;code>com.amazon.Lassen&lt;/code>）：Mac 原生 App 使用 bundle ID 當目錄名。從名字就能辨識——&lt;code>com.amazon&lt;/code> 是 Amazon、&lt;code>com.docker.docker&lt;/code> 是 Docker。&lt;/p>
&lt;p>&lt;strong>UUID&lt;/strong>（例如 &lt;code>D678BD0C-AEB0-4E05-B0D2-58F5C45F0207&lt;/code>）：&lt;a href="../macos_ios_app_on_mac/">iOS App on Mac&lt;/a> 使用 UUID 當目錄名，從名字完全無法辨識是哪個 App。辨識方法是讀 Container 根部的 &lt;code>.com.apple.containermanagerd.metadata.plist&lt;/code>（見 &lt;a href="../macos_identify_app_containers/">辨識 App 容器&lt;/a>）。&lt;/p>
&lt;h2 id="佔用的兩類快取-vs-資料">佔用的兩類：快取 vs 資料&lt;/h2>
&lt;p>清理 Container 時要判斷佔用的性質——快取刪了會自動重建，資料刪了就消失。&lt;/p>
&lt;p>&lt;strong>快取類&lt;/strong>（&lt;code>Data/Library/Caches/&lt;/code>、&lt;code>Data/tmp/&lt;/code>）：App 產生的衍生物，刪除後 App 自動重建。清除零風險，最多讓 App 下次啟動慢一點或需要重新登入。&lt;/p>
&lt;p>&lt;strong>資料類&lt;/strong>（&lt;code>Data/Documents/&lt;/code>、&lt;code>Data/Library/Application Support/&lt;/code>）：使用者資料——遊戲的下載資源、電子書的離線書庫、聊天紀錄、筆記資料庫。刪除後資料消失，要從雲端重新下載（如果有雲端同步的話）。&lt;/p>
&lt;p>兩類的大小比例因 App 而異。遊戲類 App 的 Documents 常佔 90% 以上（語音包、素材、更新包），快取比例很低。瀏覽器類 App 則相反，快取常佔大宗。排查時逐 App 看 &lt;code>Data/Documents&lt;/code> 和 &lt;code>Data/Library/Caches&lt;/code> 的大小分佈，才能判斷清掉能回收多少、風險是什麼。&lt;/p>
&lt;h2 id="跟-application-support-的分工">跟 Application Support 的分工&lt;/h2>
&lt;p>沙箱 App 的資料全部在自己的 Container 裡。非沙箱 App 的資料則散在 &lt;code>~/Library&lt;/code> 的公共位置——&lt;code>Application Support&lt;/code>、&lt;code>Caches&lt;/code>、&lt;code>Preferences&lt;/code> 等。同一個開發商的 App 可能有些啟用沙箱（Container 裡一份完整資料）、有些沒有（散在公共位置），兩者的佔用要分開看。&lt;/p></description><content:encoded><![CDATA[<p><code>~/Library/Containers</code> 是 macOS 沙箱（App Sandbox）機制的產物。每個啟用沙箱的 App 在這裡有一個獨立的目錄，作為該 App 的隔離環境。排查磁碟空間時，Containers 常是 <code>~/Library</code> 裡最大的子目錄之一，理解它的結構才能判斷哪些佔用是可以清除的快取、哪些是動不得的使用者資料。</p>
<h2 id="沙箱的設計目的">沙箱的設計目的</h2>
<p>App Sandbox 限制每個 App 只能存取自己的資料，不能碰其他 App 或使用者的檔案。這個隔離不是建議性的——沙箱由作業系統核心強制執行，App 程式碼裡寫了讀取其他 App 目錄的路徑，系統會拒絕。</p>
<p>Mac App Store 上架的 App 必須啟用沙箱。非 App Store 分發的 App 可以選擇不啟用，但越來越多開發者主動啟用以獲得使用者信任。</p>
<p>每個沙箱 App 拿到的是一個完整的家目錄副本——裡面有 <code>Documents</code>、<code>Library</code>、<code>Downloads</code> 等跟使用者家目錄一樣的子目錄，但 App 看到的路徑是自己的副本，不是使用者真正的家目錄。這些副本就放在 <code>~/Library/Containers/&lt;bundle-id&gt;/Data/</code> 下。</p>
<h2 id="container-的內部結構">Container 的內部結構</h2>
<p>每個 Container 的結構是固定的：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">~/Library/Containers/&lt;bundle-id&gt;/
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── .com.apple.containermanagerd.metadata.plist  # 容器 metadata
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">└── Data/
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    ├── Documents/      # App 的文件（使用者資料）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    ├── Library/        # App 的 Library（設定、快取、資料庫）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    │   ├── Caches/     # 快取（可安全清除）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    │   ├── Preferences/# 設定
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    │   └── ...
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    ├── Downloads/      # 有的是 symlink 到使用者的 ~/Downloads
</span></span><span class="line"><span class="ln">10</span><span class="cl">    ├── Desktop/        # 通常是 symlink
</span></span><span class="line"><span class="ln">11</span><span class="cl">    ├── tmp/            # 暫存
</span></span><span class="line"><span class="ln">12</span><span class="cl">    └── StoreKit/       # App Store 相關</span></span></code></pre></div><p><code>Downloads</code>、<code>Desktop</code>、<code>Movies</code>、<code>Music</code>、<code>Pictures</code> 多數是 symlink（符號連結）指向使用者的對應目錄——沙箱允許 App 透過使用者授權存取這些位置。<code>du</code> 加 <code>-x</code> 旗標時不會跨越 symlink 計入，所以不會重複計算。</p>
<h2 id="命名慣例bundle-id-vs-uuid">命名慣例：bundle ID vs UUID</h2>
<p>Container 目錄的命名方式取決於 App 的來源。</p>
<p><strong>Bundle ID</strong>（App 的唯一識別碼，格式為反向域名，例如 <code>com.amazon.Lassen</code>）：Mac 原生 App 使用 bundle ID 當目錄名。從名字就能辨識——<code>com.amazon</code> 是 Amazon、<code>com.docker.docker</code> 是 Docker。</p>
<p><strong>UUID</strong>（例如 <code>D678BD0C-AEB0-4E05-B0D2-58F5C45F0207</code>）：<a href="../macos_ios_app_on_mac/">iOS App on Mac</a> 使用 UUID 當目錄名，從名字完全無法辨識是哪個 App。辨識方法是讀 Container 根部的 <code>.com.apple.containermanagerd.metadata.plist</code>（見 <a href="../macos_identify_app_containers/">辨識 App 容器</a>）。</p>
<h2 id="佔用的兩類快取-vs-資料">佔用的兩類：快取 vs 資料</h2>
<p>清理 Container 時要判斷佔用的性質——快取刪了會自動重建，資料刪了就消失。</p>
<p><strong>快取類</strong>（<code>Data/Library/Caches/</code>、<code>Data/tmp/</code>）：App 產生的衍生物，刪除後 App 自動重建。清除零風險，最多讓 App 下次啟動慢一點或需要重新登入。</p>
<p><strong>資料類</strong>（<code>Data/Documents/</code>、<code>Data/Library/Application Support/</code>）：使用者資料——遊戲的下載資源、電子書的離線書庫、聊天紀錄、筆記資料庫。刪除後資料消失，要從雲端重新下載（如果有雲端同步的話）。</p>
<p>兩類的大小比例因 App 而異。遊戲類 App 的 Documents 常佔 90% 以上（語音包、素材、更新包），快取比例很低。瀏覽器類 App 則相反，快取常佔大宗。排查時逐 App 看 <code>Data/Documents</code> 和 <code>Data/Library/Caches</code> 的大小分佈，才能判斷清掉能回收多少、風險是什麼。</p>
<h2 id="跟-application-support-的分工">跟 Application Support 的分工</h2>
<p>沙箱 App 的資料全部在自己的 Container 裡。非沙箱 App 的資料則散在 <code>~/Library</code> 的公共位置——<code>Application Support</code>、<code>Caches</code>、<code>Preferences</code> 等。同一個開發商的 App 可能有些啟用沙箱（Container 裡一份完整資料）、有些沒有（散在公共位置），兩者的佔用要分開看。</p>
<p><a href="../macos_app_footprint_report/">App 聚合佔用報告</a> 的 <code>app-report</code> 腳本把 Container 和公共位置的佔用聚合回各 App，就是處理這個分散的問題。</p>
<h2 id="group-containers">Group Containers</h2>
<p><code>~/Library/Group Containers/</code> 是同一個開發商旗下多個 App 共享資料的位置。目錄名前面多一段 team ID（10 碼英數，像 <code>HUAQ24HBR6.dev.orbstack</code>）。清理時要注意：動一個 Group Container 可能影響同廠商的多個 App。</p>
]]></content:encoded></item></channel></rss>