> For the complete documentation index, see [llms.txt](https://ayakaleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayakaleaf-pro.ayaka.space/on-premises/zh-tw/she-ding/overleaf-toolkit/sandboxed-compiles.md).

# 沙箱化編譯

Overleaf Pro 提供在受保護的沙箱環境中執行編譯的選項，以滿足企業安全需求。它透過在各自獨立且受保護的 Docker 環境中執行每個專案來達成。

### 更佳的安全性

由於許多 LaTeX 文件需要／可在 PDF 編譯流程中執行任意 shell 指令，因此對於 Server Pro，建議使用沙箱化編譯。若您使用沙箱化編譯，每次編譯都會在一個獨立的 Docker 容器中執行，具有限制的功能，且不與任何其他使用者或專案共用，並且無法存取外部資源，例如主機網路。

{% hint style="warning" %}
如果您嘗試執行 Overleaf Pro **而不使用** Sandboxed Compiles，編譯會與其他同時進行的編譯一起在主要的 Docker 容器內執行，而且使用者對於在執行 LaTeX 編譯時的 `sharelatex` 容器資源（檔案系統、網路與環境變數）具有完整的讀寫權限。
{% endhint %}

### 更容易的套件管理

為避免手動安裝套件，我們建議啟用沙箱化編譯。這是 Server Pro 中的一項可設定選項，可讓您的使用者在您自己的內部部署安裝中，使用與 overleaf.com 相同的 TeX Live 環境。沙箱化編譯使用的 TeX Live 映像包含最常用的套件與字型，並已針對我們的畫廊範本進行測試，可確保與內部部署專案的最大相容性。

啟用沙箱化編譯後，您可以設定使用者可在其專案中選擇哪些 TeX Live 版本，並為新專案設定預設的 TeX Live 映像版本。

{% hint style="info" %}
如果您嘗試在未啟用沙箱化編譯的情況下執行 Overleaf Pro，您的執行個體會預設使用基本方案版本的 TeX Live 進行編譯。這個基本版本很輕量，只包含極少量的 LaTeX 套件，因此很可能會導致您的使用者出現缺少套件的錯誤，特別是當他們嘗試使用預先建置的範本時。
{% endhint %}

由於 Overleaf Pro 的架構設計為可離線運作，因此沒有自動化方式可將 overleaf.com 的畫廊範本整合到您的內部部署安裝中；不過，仍可針對每個範本手動進行。若要了解其運作方式，請參閱我們的從 overleaf.com 轉移範本指南： [/pages/17e98813f59d6ed57c0dfa0721b9c99628ebfc60#transferring-templates-from-overleaf.com](https://ayakaleaf-pro.ayaka.space/on-premises/zh-tw/she-ding/overleaf-toolkit/pages/17e98813f59d6ed57c0dfa0721b9c99628ebfc60#transferring-templates-from-overleaf.com "mention").

{% hint style="info" %}
沙箱化編譯要求 `sharelatex` 容器可透過繫結掛載存取主機機器上的 Docker socket，以便管理這些相鄰的編譯容器。
{% endhint %}

## 運作方式

啟用沙箱化編譯後，Docker socket 會從主機機器掛載到 `sharelatex` 容器中，讓容器內的編譯器服務可以在主機上建立新的 Docker 容器。接著，對每個專案中的每次編譯，LaTeX 編譯器服務（CLSI）會執行以下操作：

* 將專案檔案寫入位於 `OVERLEAF_DATA_PATH`.
* 使用已掛載的 Docker socket 建立新的 `texlive` 容器以供該次編譯執行。
* 讓 `texlive` 容器從位於以下路徑下的位置讀取專案資料： `OVERLEAF_DATA_PATH`.
* 在 `texlive` 容器內編譯專案。

### 啟用沙箱化編譯

#### 適用於 Toolkit 使用者

若要啟用沙箱化編譯（亦稱為同層容器），請在 `overleaf-toolkit/config/overleaf.rc`:

{% code title="config/overleaf.rc" %}

```dotenv
SERVER_PRO=true
SIBLING_CONTAINERS_ENABLED=true
```

{% endcode %}

#### 適用於 Docker Compose 使用者 <a href="#docker-compose-example" id="docker-compose-example"></a>

{% hint style="danger" %}
自 Overleaf CE/Server Pro 起 `5.0.3` 環境變數已重新命名，從 `SHARELATEX_*` 改為 `OVERLEAF_*`.
{% endhint %}

如果您使用的是 `4.x` 版本（或更早版本），請務必將變數以前綴正確標示（例如 `SHARELATEX_MONGO_URL` 而不是 `OVERLEAF_MONGO_URL`).

<pre class="language-yml"><code class="lang-yml">version: '2'
services:
    sharelatex:
        #...
        volumes:
            - /data/overleaf_data:/var/lib/overleaf
<strong>            - /var/run/docker.sock:/var/run/docker.sock
</strong>        environment:
            #...
<strong>            DOCKER_RUNNER: "true"
</strong><strong>            SANDBOXED_COMPILES: "true"
</strong><strong>            SANDBOXED_COMPILES_HOST_DIR: "/data/overleaf_data/data/compiles"
</strong>            #...
        #...
</code></pre>

### 變更 TexLive 映像

{% hint style="info" %}
中國大陸使用者可使用 `ghcr.nju.edu.cn` 以加速下載。
{% endhint %}

Overleaf Pro 使用三個環境變數來決定沙箱化編譯要使用哪些 TeX Live 映像：

* `TEX_LIVE_DOCKER_IMAGE` **（必填），** 用於編譯新專案的預設 TeX Live 映像。此映像必須包含在 `ALL_TEX_LIVE_DOCKER_IMAGES`.
* `ALL_TEX_LIVE_DOCKER_IMAGE_NAMES` **（必填），** 以逗號分隔的友善名稱清單，用於前端選項。
* `ALL_TEX_LIVE_DOCKER_IMAGES` **（必填），** 以逗號分隔的 TeX Live 映像清單。若使用 Overleaf Toolkit 進行部署，這些映像會被下載或更新。若要略過下載，請設定 `SIBLING_CONTAINERS_PULL=false` 於 `config/overleaf.rc`.

當您使用以下方式啟動 Overleaf Pro 執行個體時： `bin/up` 指令，Toolkit 會自動拉取列於 `ALL_TEX_LIVE_DOCKER_IMAGES`.

以下是一個範例：我們將新專案預設為 TeX Live 2025，並讓現有專案繼續使用 2024。

{% tabs %}
{% tab title="一般安裝" %}
以下設定會安裝 2025 到 2026 的所有完整 TeX Live Docker 映像。在使用此設定前，我們建議至少準備 80 GB 的可用儲存空間。

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
ALL_TEX_LIVE_DOCKER_IMAGES=ghcr.io/ayaka-notes/texlive-full:2026.1, ghcr.io/ayaka-notes/texlive-full:2025.1
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=Texlive 2026, Texlive 2025
TEX_LIVE_DOCKER_IMAGE=ghcr.io/ayaka-notes/texlive-full:2026.1
```

{% endcode %}
{% endtab %}

{% tab title="完整安裝" %}
以下設定會安裝 2020 到 2026 的所有完整 TeX Live Docker 映像。在使用此設定前，我們建議至少準備 256 GB 的可用儲存空間。

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
ALL_TEX_LIVE_DOCKER_IMAGES=ghcr.io/ayaka-notes/texlive-full:2026.1,ghcr.io/ayaka-notes/texlive-full:2025.1,ghcr.io/ayaka-notes/texlive-full:2024.1,ghcr.io/ayaka-notes/texlive-full:2023.1,ghcr.io/ayaka-notes/texlive-full:2022.1,ghcr.io/ayaka-notes/texlive-full:2021.1,ghcr.io/ayaka-notes/texlive-full:2020.1
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=Texlive 2026,Texlive 2025,Texlive 2024,Texlive 2023,Texlive 2022,Texlive 2021,Texlive 2020
TEX_LIVE_DOCKER_IMAGE=ghcr.io/ayaka-notes/texlive-full:2026.1
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
強烈建議設定 **至少 2 個 texlive-full 映像**。詳細原因請見 [#known-issues](#known-issues "mention")
{% endhint %}

### 可用的 TeX Live 映像

這是一系列專為 Overleaf 最佳化的 TeX Live 映像，也可以加入到 `TEX_LIVE_DOCKER_IMAGE` 以及 `ALL_TEX_LIVE_DOCKER_IMAGES`:

* `ghcr.io/ayaka-notes/texlive-full:2026.1` （亦可使用 `latest` 標籤）
* `ghcr.io/ayaka-notes/texlive-full:2025.1`
* `ghcr.io/ayaka-notes/texlive-full:2024.1`
* `ghcr.io/ayaka-notes/texlive-full:2023.1`
* `ghcr.io/ayaka-notes/texlive-full:2022.1`
* `ghcr.io/ayaka-notes/texlive-full:2021.1`
* `ghcr.io/ayaka-notes/texlive-full:2020.1`

{% hint style="warning" %}
關於映像如何 **必須** 標記，有嚴格的結構要求（以下正則表示式適用 `^[0-9]+.[0-9]+`，其中第一個數字代表 TeX Live 年份，第二個數字代表修補版本）。
{% endhint %}

### 我可以使用其他映像註冊庫嗎

> 有些人可能會想，我是否可以將 `ghcr.io` 替換成其他鏡像站，或把 texlive 改成 Docker Hub 上的其他映像？

不，我們不建議這麼做，因為設定相對複雜。如果您是從鏡像站下載，您可以將映像重新命名為 `ghcr.io/ayaka-notes/texlive-full`.

但是，如果您真的想使用自己的映像註冊庫，請加入：

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
IMAGE_ROOT=hub.your.com/your-repo
```

{% endcode %}

接著，您需要確認 texlive 的所有映像都位於 `your-repo`，例如

* `hub.your.com/your-repo/texlive-full:2025.1`
* `hub.your.com/your-repo/texlive-full:2024.1`

如需詳細資訊，請閱讀下方原始碼，了解我們如何解析您的環境變數：

{% code title="sandboxed-compiles/index.mjs" overflow="wrap" expandable="true" %}

```mjs
if (process.env.SANDBOXED_COMPILES === 'true') {
  // 如果未提供，則設定預設映像根路徑
  let imageRootPath = process.env.IMAGE_ROOT || "ghcr.io/ayaka-notes";
  // 將 imageRoot 匯出到 Settings
  Settings.imageRoot = imageRootPath

  // allowedImageNames 應為：
  // [
  //  { imageName: "texlive-2023:latest", imageDesc: "TeX Live 2023" },
  //  { imageName: "texlive-2022:latest", imageDesc: "TeX Live 2022" },
  // ]
  Settings.allowedImageNames = parseTextExtensions(process.env.ALL_TEX_LIVE_DOCKER_IMAGES)
    .map((texImage, index) => ({
      imageName: texImage.split("/")[texImage.split("/").length - 1],
      imageDesc: parseTextExtensions(process.env.ALL_TEX_LIVE_DOCKER_IMAGE_NAMES)[index]
        || texImage.split(':')[1],
    }))
  
  // 最後，imageName 會與 imageRoot 組合成完整的映像路徑
  // 完整名稱會像這樣：ghcr.io/ayaka-notes/texlive-2023:latest

  // 如果未提供，則設定預設映像名稱
  if(!process.env.TEX_LIVE_DOCKER_IMAGE) {
    process.env.TEX_LIVE_DOCKER_IMAGE = imageRootPath + "/" + Settings.allowedImageNames[0].imageName
  }

  // 將 currentImageName 匯出到 Settings
  // 這是新建立專案的映像名稱
  Settings.currentImageName = process.env.TEX_LIVE_DOCKER_IMAGE
}
```

{% endcode %}

### 已知問題

這是來自 Overleaf 社群的真實案例：

> 使用 `6.0.1-ext-v3.3`時，我在 `variables.env`:
>
> ```dotenv
> TEX_LIVE_DOCKER_IMAGE=texlive/texlive:latest-full
> ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texlive:latest-full
> ```
>
> 這在以下情況下運作正常： `texlive/texlive:latest-full`。不過，我又拉取了另一個 texlive 映像 `danteev/texlive:2025-10-15` 並將這兩個變數都改成新的映像名稱，但它無法運作：
>
> ```dotenv
> TEX_LIVE_DOCKER_IMAGE=danteev/texlive:2025-10-15
> ALL_TEX_LIVE_DOCKER_IMAGES=danteev/texlive:2025-10-15
> ```
>
> 在日誌中，我看到以下內容：
>
> {% code overflow="wrap" %}
>
> ```
> {"name":"clsi","level":50,"err":{"message":"(HTTP code 404) no such container - No such image: texlive/texlive:latest-full ","name":"Error","stack":"Error: (HTTP code 404) no such container - No such image: texlive/texlive:latest-full ... 
> ```
>
> {% endcode %}
>
> 看起來在 `variables.env` 中的更新設定沒有生效。編譯仍然嘗試執行 `texlive/texlive:latest-full` 映像，而不是新的映像。
>
> 我試過重新啟動、刪除容器並重新執行，但問題仍然一樣。
>
> 有解決方法嗎？

由於一些技術限制，如果您只設定單一個 Docker TeXLive 映像，例如 `texlive-fullA:latest`

```
ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texliveA:latest-full
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLiveA
TEX_LIVE_DOCKER_IMAGE=texlive/texliveA:latest-full
```

在讓您的 overleaf 執行個體運行一段時間後，您可能會想將 TeXLive 映像修改為 `texlive-fullB:latest`。接著，您會發現使用者無法編譯所有專案。

```
ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texliveA:latest-full
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLiveA
TEX_LIVE_DOCKER_IMAGE=texlive/texliveA:latest-full
```

這是因為每個專案中 TeXLive-Full 映像（用於沙箱編譯）的名稱都會保留在資料庫中。 *只有當使用者切換其專案的 TeXLive 版本，例如從 2024 切換到 2025 時，資料庫中的映像名稱才會變更*.

當 CLSI 編譯專案時，會直接使用資料庫中找到的容器映像名稱來編譯該專案。

如果您只提供一個 Docker 映像，使用者將無法修改用於編譯專案的映像。在這種情況下，您需要撰寫腳本來 **手動修改** 所有使用者專案在 mongoDB 中的 TeXLive 映像。

### 除錯

執行以下指令以檢查 toolkit 中的 clsi 日誌：

{% code overflow="wrap" %}

```bash
bin/logs clsi
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ayakaleaf-pro.ayaka.space/on-premises/zh-tw/she-ding/overleaf-toolkit/sandboxed-compiles.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
