> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 沙箱編譯（Sandboxed Compiles）

Ayakaleaf Pro 提供在安全沙箱環境中執行編譯的選項，以滿足企業級的安全需求。其做法是讓每個專案都在各自獨立且安全的 Docker 環境中執行。

### 更高的安全性

由於許多 LaTeX 文件在 PDF 編譯過程中需要（或具備）執行任意 shell 指令的能力，因此 Sandboxed Compiles 是 Ayakaleaf Pro 建議採用的方式。如果您使用 Sandboxed Compiles，每次編譯都會在獨立的 Docker 容器中執行，該容器權限受限、不與任何其他使用者或專案共用，且無法存取主機網路等外部資源。

<Warning>
  如果您嘗試在**未**啟用 Sandboxed Compiles 的情況下執行 Ayakaleaf Pro，編譯將會與其他同時進行的編譯一起在主要 Docker 容器內執行，且使用者在執行 LaTeX 編譯時，對 `sharelatex` 容器的資源（檔案系統、網路與環境變數）擁有完整的讀寫權限。
</Warning>

### 更簡便的套件管理

為了避免手動安裝套件，我們建議啟用 Sandboxed Compiles。這是 Server Pro 中的一項可設定選項，能讓您的使用者在您自己的地端安裝中，使用與 overleaf.com 相同的 TeX Live 環境。Sandboxed Compiles 所使用的 TeX Live 映像檔包含最熱門的套件與字型，並已針對我們的範本庫進行測試，確保與地端專案有最高的相容性。

啟用 Sandboxed Compiles 後，您可以設定使用者在專案中可選擇的 TeX Live 版本，並為新專案設定預設的 TeX Live 映像檔版本。

<Info>
  如果您嘗試在未啟用 Sandboxed Compiles 的情況下執行 Ayakaleaf Pro，您的執行個體將預設使用 basic scheme 版本的 TeX Live 進行編譯。這個基本版本相當輕量，只包含非常有限的 LaTeX 套件子集，很可能會導致使用者遇到缺少套件的錯誤，尤其是在嘗試使用預先建置的範本時。
</Info>

由於 Ayakaleaf Pro 的架構設計為可離線運作，因此沒有自動化的方式能將 overleaf.com 範本庫中的範本整合到您的地端安裝中；不過，您可以逐一手動匯入範本。如需了解其運作方式，請參閱我們從 overleaf.com 轉移範本的指南：[#transferring-templates-from-overleaf.com](/zh-TW/on-premises/configuration/overleaf-toolkit/templates#transferring-templates-from-overleaf.com "mention")。

<Info>
  Sandboxed Compiles 需要 `sharelatex` 容器能（透過綁定掛載）存取主機上的 Docker socket，以便管理這些同層級的編譯容器。
</Info>

## 運作方式

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

* 將專案檔案寫入 `OVERLEAF_DATA_PATH` 內的某個位置。
* 使用掛載的 Docker socket 為此次編譯建立新的 `texlive` 容器。
* 讓 `texlive` 容器從 `OVERLEAF_DATA_PATH` 下的位置讀取專案資料。
* 在 `texlive` 容器內編譯專案。

### 啟用 Sandboxed Compiles

#### Toolkit 使用者

要啟用沙箱編譯（也稱為 Sibling containers），請在 `overleaf-toolkit/config/overleaf.rc` 中設定以下選項：

```dotenv title="config/overleaf.rc" theme={null}
SERVER_PRO=true
SIBLING_CONTAINERS_ENABLED=true
```

#### Docker Compose 使用者

<Danger>
  從 Overleaf CE/Server Pro `5.0.3` 開始，環境變數已從 `SHARELATEX_*` 更名為 `OVERLEAF_*`。
</Danger>

如果您使用的是 `4.x`（或更早）版本，請確認變數使用相應的前綴（例如使用 `SHARELATEX_MONGO_URL` 而非 `OVERLEAF_MONGO_URL`）。

```yml theme={null}
version: '2'
services:
    sharelatex:
        #...
        volumes:
            - /data/overleaf_data:/var/lib/overleaf
            - /var/run/docker.sock:/var/run/docker.sock
        environment:
            #...
            DOCKER_RUNNER: "true"
            SANDBOXED_COMPILES: "true"
            SANDBOXED_COMPILES_HOST_DIR: "/data/overleaf_data/data/compiles"
            #...
        #...
```

### 設定 TeX Live 映像檔

<Info>
  中國大陸的使用者可以將 `ghcr.io` 替換為 `ghcr.nju.edu.cn` 以加快下載速度。但**請勿**在 Toolkit 的環境設定中直接使用 `ghcr.nju.edu.cn`，您應該只使用 `ghcr.io`。
</Info>

Ayakaleaf Pro 使用三個環境變數來決定 Sandboxed Compiles 要使用哪些 TeX Live 映像檔：

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

使用 `bin/up` 指令啟動 Ayakaleaf Pro 執行個體時，Toolkit 會自動拉取 `ALL_TEX_LIVE_DOCKER_IMAGES` 中列出的所有映像檔。

以下範例中，新專案預設使用 TeX Live 2026，舊專案則繼續使用 2025。

<Tabs>
  <Tab title="最小安裝">
    以下設定會安裝 2025 到 2026 年的所有完整 TeX Live Docker 映像檔。使用此設定前，建議至少準備 **64 GB** 的可用儲存空間。

    ```dotenv title="config/variables.env" wrap theme={null}
    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
    ```
  </Tab>

  <Tab title="完整安裝">
    以下設定會安裝 2020 到 2026 年的所有完整 TeX Live Docker 映像檔。使用此設定前，建議至少準備 **150 GB** 的可用儲存空間。

    ```dotenv title="config/variables.env" wrap theme={null}
    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
    ```
  </Tab>
</Tabs>

<Danger>
  強烈建議**至少設定 2 個 texlive-full 映像檔**。詳細原因請參閱 [#known-issues](/zh-TW/on-premises/configuration/overleaf-toolkit/sandboxed-compiles#known-issues "mention")
</Danger>

### 可用的 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`

<Warning>
  映像檔的標籤**必須**遵循嚴格的格式（適用的正規表示式為 `^[0-9]+.[0-9]+`，其中第一個數字決定 TeX Live 年份，第二個數字則為修補版本）。
</Warning>

### 可以使用其他映像檔登錄庫嗎？

> 有些人可能會想，能否將 `ghcr.io` 替換為其他鏡像站，或將 texlive 改用 Docker Hub 上的其他映像檔？

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

但如果您確實想使用自己的映像檔登錄庫，請加入：

```dotenv title="config/variables.env" wrap theme={null}
IMAGE_ROOT=hub.your.com/your-repo
```

接著，您需要確保所有 texlive 映像檔都位於 `your-repo` 中，例如：

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

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

```mjs title="sandboxed-compiles/index.mjs" wrap expandable theme={null}
if (process.env.SANDBOXED_COMPILES === 'true') {
  // Set default image root if not provided
  let imageRootPath = process.env.IMAGE_ROOT || "ghcr.io/ayaka-notes";
  // Export imageRoot to Settings
  Settings.imageRoot = imageRootPath

  // allowedImageNames should be:
  // [
  //  { 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],
    }))
  
  // In the end, imageName will be put together with imageRoot to form the full image path
  // The full name will be like: ghcr.io/ayaka-notes/texlive-2023:latest

  // Set default image name if not provided
  if(!process.env.TEX_LIVE_DOCKER_IMAGE) {
    process.env.TEX_LIVE_DOCKER_IMAGE = imageRootPath + "/" + Settings.allowedImageNames[0].imageName
  }

  // Export currentImageName to Settings
  // This is the new created projects' image name
  Settings.currentImageName = process.env.TEX_LIVE_DOCKER_IMAGE
}
```

### 自動同步 TeX Live 映像檔

為了避免每次都要手動執行 `bin/up` 更新執行個體，您可以將 TeX Live 映像檔的更新自動化。請參閱 [updating-tex-live-full-images-automatically.md](/zh-TW/on-premises/maintenance/updating-tex-live-full-images-automatically "mention")。

### 已知問題

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

> 我使用 `6.0.1-ext-v3.3`，在 `variables.env` 中有以下設定：
>
> ```dotenv theme={null}
> 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 theme={null}
> TEX_LIVE_DOCKER_IMAGE=danteev/texlive:2025-10-15
> ALL_TEX_LIVE_DOCKER_IMAGES=danteev/texlive:2025-10-15
> ```
>
> 在記錄中，我看到以下內容：
>
> ```text wrap theme={null}
> {"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 ... 
> ```
>
> 看起來 `variables.env` 中更新的設定並未生效。編譯仍然嘗試執行 `texlive/texlive:latest-full` 映像檔，而不是新的映像檔。
>
> 我試過重新開機、刪除容器後重新執行，但問題依舊。
>
> 有什麼解決辦法嗎？

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

```text theme={null}
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`。這時，您會發現使用者無法編譯任何專案。

```text theme={null}
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 記錄：

```bash wrap theme={null}
bin/logs clsi
```

如果您在使用 TeX Live 映像檔編譯時遇到任何問題，請在此提交 issue：

[https://github.com/ayaka-notes/texlive-full/issues/new?template=texlive-image-bug.yml](https://github.com/ayaka-notes/texlive-full/issues/new?template=texlive-image-bug.yml)

為了協助我們重現並排除問題，我們可能會請您將專案上傳到 Overleaf。接著我們會拉取該專案，並透過 GitHub Action 執行編譯測試。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.