Files
bentopdf/docs/zh-TW/self-hosting/docker.md
T

631 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 使用 Docker / Podman 部署
在正式環境中自行架設 BentoPDF 最簡單的方式。
> [!IMPORTANT]
> **Office 檔案轉換所需的標頭**
>
> 以 LibreOffice 為基礎的工具(Word、Excel、PowerPoint 轉換)需要以下 HTTP 標頭才能支援 `SharedArrayBuffer`:
>
> - `Cross-Origin-Opener-Policy: same-origin`
> - `Cross-Origin-Embedder-Policy: require-corp`
>
> 頁面也必須在安全環境(secure context)中提供。`http://localhost` 可用於本機測試,但 `http://192.168.x.x` 或其他區域網路 IP 通常不符合條件,因此即使標頭存在,透過一般 HTTP 進行 Office 轉換仍會失敗。
>
> 官方容器映像已包含這些標頭。若使用反向代理(Traefik、Caddy 等),請確保保留或加入這些標頭,並在非迴路位址存取時使用 HTTPS。
> [!TIP]
> **Podman 使用者:** 只要將 `docker` 換成 `podman`、將 `docker-compose` 換成 `podman-compose`,所有 `docker` 指令都可在 Podman 上使用。
## 快速開始
> [!TIP]
> BentoPDF 提供兩種版本:
>
> - **自行架設版**:`ghcr.io/alam00000/bentopdf-simple:latest`。包含所有 PDF 工具,但**不含**行銷介面(沒有主視覺、常見問題、使用者推薦、頁尾)。適用於內部、團隊或組織部署。它**不是**功能縮減的「精簡」版本。
> - **商業版**:`ghcr.io/alam00000/bentopdf:latest`。完整的行銷網站,由 bentopdf.com 本身以及執行對外公開部署的商業授權持有者使用。
>
> 如果不確定,請拉取自行架設版。
```bash
# Docker
docker run -d \
--name bentopdf \
-p 3000:8080 \
--restart unless-stopped \
ghcr.io/alam00000/bentopdf-simple:latest
# Podman
podman run -d \
--name bentopdf \
-p 3000:8080 \
ghcr.io/alam00000/bentopdf-simple:latest
```
## Docker Compose / Podman Compose
建立 `docker-compose.yml`:
```yaml
services:
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:latest
container_name: bentopdf
ports:
- '3000:8080'
restart: unless-stopped
healthcheck:
test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:8080']
interval: 30s
timeout: 10s
retries: 3
```
執行:
```bash
# Docker Compose
docker compose up -d
# Podman Compose
podman-compose up -d
```
## 建置自己的映像
```dockerfile
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
ENV HUSKY=0
COPY package*.json ./
COPY vendor ./vendor
RUN npm ci
COPY . .
RUN npm run build
FROM nginxinc/nginx-unprivileged:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
COPY nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /etc/nginx/tmp
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
```
建置並執行:
```bash
docker build -t bentopdf:custom .
docker run -d -p 3000:8080 bentopdf:custom
```
## 環境變數
| 變數 | 說明 | 預設值 |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `SIMPLE_MODE` | 建置自行架設版(隱藏 bentopdf.com 行銷介面:主視覺、常見問題、使用者推薦、頁尾)。所有 PDF 工具都會保留。 | `false` |
| `BASE_URL` | 部署到子目錄 | `/` |
| `VITE_WASM_PYMUPDF_URL` | PyMuPDF WASM 模組 URL | `https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/` |
| `VITE_WASM_GS_URL` | Ghostscript WASM 模組 URL | `https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/assets/` |
| `VITE_WASM_CPDF_URL` | CoherentPDF WASM 模組 URL | `https://cdn.jsdelivr.net/npm/[email protected]/dist/` |
| `VITE_TESSERACT_WORKER_URL` | OCR worker 指令碼 URL | _(空白;使用 Tesseract.js 預設 CDN)_ |
| `VITE_TESSERACT_CORE_URL` | OCR 核心執行環境目錄 | _(空白;使用 Tesseract.js 預設 CDN)_ |
| `VITE_TESSERACT_LANG_URL` | OCR traineddata 目錄 | _(空白;使用 Tesseract.js 預設 CDN)_ |
| `VITE_TESSERACT_AVAILABLE_LANGUAGES` | 在介面中顯示的 OCR 語言,以逗號分隔 | _(空白;顯示完整清單)_ |
| `VITE_OCR_FONT_BASE_URL` | OCR 文字層字型目錄 | _(空白;使用遠端 Noto 字型 URL)_ |
| `VITE_DEFAULT_LANGUAGE` | 預設介面語言 | `en` |
| `VITE_BRAND_NAME` | 自訂品牌名稱 | `BentoPDF` |
| `VITE_BRAND_LOGO` | 相對於 `public/` 的標誌路徑 | `images/favicon-no-bg.svg` |
| `VITE_FOOTER_TEXT` | 自訂頁尾/版權文字 | `© 2026 BentoPDF. All rights reserved.` |
| `DISABLE_TOOLS` | 要隱藏的工具 ID,以逗號分隔 | _(空白;啟用所有工具)_ |
| `DISABLE_GITHUB_STARS` | 頁面載入時略過擷取 GitHub 星星數,並從 CSP 移除 `api.github.com`。Simple Mode 建置一律略過。 | `false` |
| `SITE_URL` | 寫入 canonical、hreflang 與 sitemap 連結的公開 URL。除非您希望搜尋引擎將您的部署視為獨立網站,否則請保留預設值。 | `https://www.bentopdf.com` |
| `ALLOW_INDEXING` | 使用自訂 `SITE_URL` 時,每個頁面都會標記為 `noindex`,避免您的副本在搜尋結果中與 bentopdf.com 競爭。設為 `true` 可讓搜尋引擎建立索引。 | `false` |
| `COMPRESSION_MODE` | 要儲存的預先壓縮副本:`o` 不儲存,`g` `.gz`(由映像檔內的 nginx 提供),`b` `.br`,`all` 兩者皆儲存。映像檔內的 nginx 無法提供 `.br`。 | `o` |
WASM 模組 URL 已預先設定為 CDN 預設值,所有進階功能開箱即用。離線隔離或自行架設的部署可覆寫這些值。
### 搜尋引擎
預設情況下,每個頁面都會向搜尋引擎指出 bentopdf.com 為原始來源,因此您的部署不會被視為重複內容。私人或內部執行個體不需要做任何變更。
- **讓您的執行個體完全不出現在搜尋結果中:** 以 `-e ROBOTS_NOINDEX=true` 執行容器。只需要重新啟動,不需要重新建置。
- **讓您的執行個體在搜尋結果中成為獨立網站:** 以 `--build-arg SITE_URL=https://your-domain.example --build-arg ALLOW_INDEXING=true` 建置。若沒有 `ALLOW_INDEXING=true`,自訂 `SITE_URL` 會將每個頁面標記為 `noindex`。
### Content-Security-Policy
nginx 映像附帶強制執行的 `Content-Security-Policy` 標頭。CSP 的 `script-src`、`connect-src` 與 `font-src` 指令會在**建置時**根據上方的 `VITE_*` URL 變數**產生**:您透過 `--build-arg` 傳入的任何主機都會自動加入政策。
因此:
- 若您在建置時覆寫 `VITE_CORS_PROXY_URL` 或 `VITE_WASM_*_URL`,CSP 會自動允許這些來源,無需額外設定。
- 對於 `cdn.jsdelivr.net` 上的 URL,`script-src` 只允許確切版本的套件資料夾,例如 `https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/`,而不是整個 CDN。jsDelivr 提供任何公開的 npm 套件或 GitHub 儲存庫,若允許整個主機,任何套件都能在您的執行個體上執行。其他主機上的 URL 則依來源允許。
- 若您在*執行時*透過應用程式內的進階設定頁面設定自訂 WASM URL,這些來源**不在** CSP 中,瀏覽器會封鎖對它們的擷取。這也適用於 `cdn.jsdelivr.net` 上同一套件的不同版本,因為只允許建置時設定的版本。執行時設定僅供實驗用途;若要永久使用自訂 URL,請設定對應的 `VITE_*` 建置參數。
- 覆寫全部三個 `VITE_WASM_*_URL` 值的離線隔離部署,也會從 CSP 移除這些 `cdn.jsdelivr.net` 套件資料夾(每個預設值都是被取代,而不是附加)。`cdn.jsdelivr.net` 上的 Tesseract OCR 預設值會留在政策中,直到您也設定三個 `VITE_TESSERACT_*` 值。同樣地,設定 `VITE_CORS_PROXY_URL` 會取代公開的 `bentopdf-cors-proxy.bentopdf.workers.dev` 預設值。
CSP 在 `script-src` 中包含 `'unsafe-eval'`,因為 LibreOffice WASM 執行環境(用於 Word/Excel/PowerPoint 轉換工具)與 wasm-vips 影像函式庫(用於 PDF 轉 TIFF)會透過 `new Function()` 編譯內部分派程式碼。移除它會使這些工具無法運作。如果您以 `SIMPLE_MODE`(不含 LibreOffice)建置且不需要 PDF 轉 TIFF,可以手動編輯產生的 `security-headers.conf` 移除 `'unsafe-eval'`,以取得更嚴格的政策。
OCR 方面,將 `VITE_TESSERACT_*` 變數留空即使用預設的線上資源,或三個一起設定以使用自行架設/離線 OCR。部分覆寫 OCR 設定會被拒絕,因為 worker、核心執行環境與 traineddata 目錄必須相符。若要完全離線產生可搜尋的 PDF,也請設定 `VITE_OCR_FONT_BASE_URL`,讓 OCR 文字層字型從您的內部伺服器載入,而不是公開的 Noto 字型 URL。
`VITE_DEFAULT_LANGUAGE` 設定首次造訪者的介面語言。支援的值:`en`、`ar`、`be`、`fr`、`de`、`es`、`zh`、`zh-TW`、`vi`、`tr`、`id`、`it`、`pt`、`nl`、`da`。使用者仍可切換語言,此設定只會變更預設值。
範例:
```bash
# Build with French as the default language
docker build --build-arg VITE_DEFAULT_LANGUAGE=fr -t bentopdf .
docker run -d -p 3000:8080 bentopdf
```
### 自訂品牌
將預設的 BentoPDF 標誌、名稱與頁尾文字換成您自己的。將標誌檔案放在 `public/` 資料夾(或使用現有圖片),然後在建置時傳入品牌變數:
```bash
docker build \
--build-arg VITE_BRAND_NAME="AcmePDF" \
--build-arg VITE_BRAND_LOGO="images/acme-logo.svg" \
--build-arg VITE_FOOTER_TEXT="© 2026 Acme Corp. Internal use only." \
-t acmepdf .
```
品牌設定在完整模式與 Simple Mode 中皆可使用,並可與所有其他建置時選項搭配。
### 停用特定工具
基於法規遵循或安全需求,可從介面隱藏工具。停用的工具會從首頁、搜尋結果、鍵盤快速鍵與工作流程建構器中移除。直接以 URL 存取會顯示「工具無法使用」頁面。
工具 ID 是不含 `.html` 的頁面 URL。例如工具位於 `bentopdf.com/edit-pdf.html` 時,ID 為 `edit-pdf`。
#### 查詢工具 ID
最簡單的方法:在 BentoPDF 中開啟任一工具並查看 URL。路徑的最後一段(不含 `.html`)就是工具 ID。
<details>
<summary>完整工具 ID 清單</summary>
**編輯與註解:** `edit-pdf`, `bookmark`, `table-of-contents`, `page-numbers`, `add-page-labels`, `bates-numbering`, `add-watermark`, `header-footer`, `invert-colors`, `scanner-effect`, `adjust-colors`, `background-color`, `text-color`, `sign-pdf`, `add-stamps`, `remove-annotations`, `crop-pdf`, `form-filler`, `form-creator`, `remove-blank-pages`
**轉換為 PDF:** `image-to-pdf`, `jpg-to-pdf`, `png-to-pdf`, `webp-to-pdf`, `svg-to-pdf`, `bmp-to-pdf`, `heic-to-pdf`, `tiff-to-pdf`, `txt-to-pdf`, `markdown-to-pdf`, `json-to-pdf`, `csv-to-pdf`, `rtf-to-pdf`, `odt-to-pdf`, `word-to-pdf`, `excel-to-pdf`, `powerpoint-to-pdf`, `xps-to-pdf`, `mobi-to-pdf`, `epub-to-pdf`, `fb2-to-pdf`, `cbz-to-pdf`, `wpd-to-pdf`, `wps-to-pdf`, `xml-to-pdf`, `pages-to-pdf`, `odg-to-pdf`, `ods-to-pdf`, `odp-to-pdf`, `pub-to-pdf`, `vsd-to-pdf`, `psd-to-pdf`, `email-to-pdf`
**從 PDF 轉換:** `pdf-to-jpg`, `pdf-to-png`, `pdf-to-webp`, `pdf-to-bmp`, `pdf-to-tiff`, `pdf-to-cbz`, `pdf-to-svg`, `pdf-to-csv`, `pdf-to-excel`, `pdf-to-greyscale`, `pdf-to-json`, `pdf-to-docx`, `extract-images`, `pdf-to-markdown`, `prepare-pdf-for-ai`, `pdf-to-text`
**整理與管理:** `ocr-pdf`, `merge-pdf`, `alternate-merge`, `organize-pdf`, `add-attachments`, `extract-attachments`, `edit-attachments`, `pdf-multi-tool`, `pdf-layers`, `extract-tables`, `split-pdf`, `divide-pages`, `extract-pages`, `delete-pages`, `add-blank-page`, `reverse-pages`, `rotate-pdf`, `rotate-custom`, `n-up-pdf`, `pdf-booklet`, `combine-single-page`, `view-metadata`, `edit-metadata`, `pdf-to-zip`, `compare-pdfs`, `posterize-pdf`, `page-dimensions`
**最佳化與修復:** `compress-pdf`, `pdf-to-pdfa`, `fix-page-size`, `linearize-pdf`, `remove-restrictions`, `repair-pdf`, `rasterize-pdf`, `deskew-pdf`, `font-to-outline`
**安全性:** `encrypt-pdf`, `sanitize-pdf`, `decrypt-pdf`, `flatten-pdf`, `remove-metadata`, `change-permissions`, `digital-sign-pdf`, `validate-signature-pdf`, `timestamp-pdf`
</details>
#### 選項 1:建置時(Docker 建置參數)
```bash
docker build \
--build-arg DISABLE_TOOLS="edit-pdf,sign-pdf,encrypt-pdf" \
-t bentopdf .
```
這會將停用清單寫入 JavaScript bundle。變更時需要重新建置。
#### 選項 2:執行時(config.json)
將 `config.json` 檔案掛載到提供服務的目錄,無需重新建置:
```json
{
"disabledTools": ["edit-pdf", "sign-pdf", "encrypt-pdf"]
}
```
```bash
docker run -d \
-p 3000:8080 \
-v ./config.json:/usr/share/nginx/html/config.json:ro \
ghcr.io/alam00000/bentopdf-simple:latest
```
或使用 Docker Compose:
```yaml
services:
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:latest
ports:
- '3000:8080'
volumes:
- ./config.json:/usr/share/nginx/html/config.json:ro
```
兩種方法可以合併使用,清單會合併。只要工具出現在其中任一清單,就會被停用。
#### 停用編輯器功能
您也可以停用 PDF 編輯器中的特定功能(例如塗黑遮蔽、註解、表單),而不停用整個編輯器工具。在您的 `config.json` 中加入 `editorDisabledCategories`:
```json
{
"editorDisabledCategories": ["redaction", "annotation-stamp"]
}
```
<details>
<summary>完整編輯器類別清單</summary>
**縮放:** `zoom`, `zoom-in`, `zoom-out`, `zoom-fit-page`, `zoom-fit-width`, `zoom-marquee`, `zoom-level`
**註解:** `annotation`, `annotation-markup`, `annotation-highlight`, `annotation-underline`, `annotation-strikeout`, `annotation-squiggly`, `annotation-ink`, `annotation-text`, `annotation-stamp`
**形狀:** `annotation-shape`, `annotation-rectangle`, `annotation-circle`, `annotation-line`, `annotation-arrow`, `annotation-polygon`, `annotation-polyline`
**測量:** `annotation-measurement`, `mode-measure`, `annotation-distance`, `annotation-perimeter`, `annotation-area`
**表單:** `form`, `form-textfield`, `form-checkbox`, `form-radio`, `form-select`, `form-listbox`, `form-fill-mode`
**塗黑遮蔽:** `redaction`, `redaction-area`, `redaction-text`, `redaction-apply`, `redaction-clear`
**文件:** `document`, `document-open`, `document-close`, `document-print`, `document-capture`, `document-export`, `document-fullscreen`, `document-protect`
**頁面:** `page`, `spread`, `rotate`, `scroll`, `navigation`
**面板:** `panel`, `panel-sidebar`, `panel-search`, `panel-comment`
**工具:** `tools`, `pan`, `pointer`, `capture`
**選取:** `selection`, `selection-copy`
**歷程記錄:** `history`, `history-undo`, `history-redo`
</details>
類別具有階層關係:停用上層類別(例如 `annotation`)會停用其所有子類別。
### 停用 GitHub 星星計數器
導覽列會顯示即時的 GitHub 星星數,於頁面載入時從 `api.github.com` 擷取。這是唯一一個並非用於 PDF 功能的外部請求。在建置時停用它,即可從 bundle 移除擷取程式碼,並從 Content-Security-Policy 移除 `api.github.com`:
```bash
docker build --build-arg DISABLE_GITHUB_STARS=true -t bentopdf .
```
Simple Mode 建置(`bentopdf-simple`)一律略過星星計數器,此旗標只在商業版或自訂完整建置時需要。
### 自訂 WASM URL(離線隔離 / 自行架設)
> [!IMPORTANT]
> WASM URL 會在**建置時**寫入 JavaScript。WASM 檔案在執行時由**使用者的瀏覽器**下載,Docker 不會在建置期間下載它們。在離線隔離網路中,您必須將 WASM 檔案架設在瀏覽器可連線的內部伺服器上。
**完整離線隔離工作流程:**
```bash
# 1. On a machine WITH internet — download WASM packages
bash scripts/prepare-airgap.sh --list-ocr-languages
bash scripts/prepare-airgap.sh --search-ocr-language german
# 2. Download WASM/OCR packages
npm pack @bentopdf/[email protected]
npm pack @bentopdf/gs-wasm
npm pack coherentpdf
npm pack [email protected]
npm pack [email protected]
mkdir -p tesseract-langdata
curl -fsSL https://cdn.jsdelivr.net/npm/@tesseract.js-data/eng/4.0.0_best_int/eng.traineddata.gz -o tesseract-langdata/eng.traineddata.gz
mkdir -p ocr-fonts
curl -fsSL https://raw.githack.com/googlefonts/noto-fonts/main/hinted/ttf/NotoSans/NotoSans-Regular.ttf -o ocr-fonts/NotoSans-Regular.ttf
# 3. Build the image with your internal server URLs
docker build \
--build-arg VITE_WASM_PYMUPDF_URL=https://internal-server.example.com/wasm/pymupdf/ \
--build-arg VITE_WASM_GS_URL=https://internal-server.example.com/wasm/gs/ \
--build-arg VITE_WASM_CPDF_URL=https://internal-server.example.com/wasm/cpdf/ \
--build-arg VITE_TESSERACT_WORKER_URL=https://internal-server.example.com/wasm/ocr/worker.min.js \
--build-arg VITE_TESSERACT_CORE_URL=https://internal-server.example.com/wasm/ocr/core \
--build-arg VITE_TESSERACT_LANG_URL=https://internal-server.example.com/wasm/ocr/lang-data \
--build-arg VITE_TESSERACT_AVAILABLE_LANGUAGES=eng,deu \
--build-arg VITE_OCR_FONT_BASE_URL=https://internal-server.example.com/wasm/ocr/fonts \
-t bentopdf .
# 4. Export the image
docker save bentopdf -o bentopdf.tar
# 5. Transfer bentopdf.tar + the .tgz packages + tesseract-langdata/ + ocr-fonts/ into the air-gapped network
# 6. Inside the air-gapped network — load and run
docker load -i bentopdf.tar
# Extract WASM packages to your internal web server
mkdir -p /var/www/wasm/pymupdf /var/www/wasm/gs /var/www/wasm/cpdf /var/www/wasm/ocr/core /var/www/wasm/ocr/lang-data /var/www/wasm/ocr/fonts
tar xzf bentopdf-pymupdf-wasm-0.11.14.tgz -C /var/www/wasm/pymupdf --strip-components=1
tar xzf bentopdf-gs-wasm-*.tgz -C /var/www/wasm/gs --strip-components=1
tar xzf coherentpdf-*.tgz -C /var/www/wasm/cpdf --strip-components=1
TEMP_TESS=$(mktemp -d)
tar xzf tesseract.js-7.0.0.tgz -C "$TEMP_TESS"
cp "$TEMP_TESS/package/dist/worker.min.js" /var/www/wasm/ocr/worker.min.js
rm -rf "$TEMP_TESS"
tar xzf tesseract.js-core-7.0.0.tgz -C /var/www/wasm/ocr/core --strip-components=1
cp ./tesseract-langdata/*.traineddata.gz /var/www/wasm/ocr/lang-data/
cp ./ocr-fonts/* /var/www/wasm/ocr/fonts/
# Run BentoPDF
docker run -d -p 3000:8080 --restart unless-stopped bentopdf
```
`--ocr-languages` 請使用 `bash scripts/prepare-airgap.sh --list-ocr-languages` 列出的代碼,或以 `bash scripts/prepare-airgap.sh --search-ocr-language <term>` 依名稱搜尋。以受限的 OCR 子集建置時,請將相同代碼傳給 `VITE_TESSERACT_AVAILABLE_LANGUAGES`,讓應用程式只顯示已打包的語言。若要完全離線輸出 OCR,也請架設內附的 `ocr-fonts/` 目錄,並將 `VITE_OCR_FONT_BASE_URL` 指向它。
將變數設為空字串即可停用該模組(使用者必須透過進階設定手動設定)。
## 自訂連接埠
預設情況下,BentoPDF 在容器內監聽 `8080` 連接埠。若要變更,請在執行時設定 `PORT` 環境變數:
```bash
docker run -p 3000:9090 -e PORT=9090 ghcr.io/alam00000/bentopdf-simple:latest
```
| 變數 | 說明 | 預設值 |
| ------ | ------------------------- | ------ |
| `PORT` | 容器內的 Nginx 監聽連接埠 | `8080` |
這在標準與 nonroot Dockerfile 中皆可使用。
## 自訂使用者 ID(PUID/PGID)
對於需要以特定非 root 使用者執行的環境(NAS 裝置、具有安全性內容的 Kubernetes、組織政策),BentoPDF 提供另一個支援 LSIO 風格 PUID/PGID 的 Dockerfile。
### 建置並執行
```bash
# Build the non-root image
docker build -f Dockerfile.nonroot -t bentopdf-nonroot .
# Run with custom UID/GID
docker run -d \
--name bentopdf \
-p 3000:8080 \
-e PUID=1000 \
-e PGID=1000 \
--restart unless-stopped \
bentopdf-nonroot
```
### 環境變數
| 變數 | 說明 | 預設值 |
| -------------- | --------------------- | ------- |
| `PUID` | 執行時使用的使用者 ID | `1000` |
| `PGID` | 執行時使用的群組 ID | `1000` |
| `PORT` | Nginx 監聽連接埠 | `8080` |
| `DISABLE_IPV6` | 停用 IPv6 監聽 | `false` |
### Docker Compose
```yaml
services:
bentopdf:
build:
context: .
dockerfile: Dockerfile.nonroot
container_name: bentopdf
ports:
- '3000:8080'
environment:
- PUID=1000
- PGID=1000
restart: unless-stopped
```
### 運作方式
容器以 root 啟動,建立具有指定 PUID/PGID 的使用者,調整所有可寫入目錄的擁有權,然後使用 `su-exec` 降低權限。nginx 程序完全以您指定的使用者執行。
> [!NOTE]
> 標準 `Dockerfile` 使用 `nginx-unprivileged`(UID 101),建議大多數部署使用。只有在需要特定 UID/GID 時才使用 `Dockerfile.nonroot`。
> [!WARNING]
> PUID/PGID 不可為 `0`(root)。entrypoint 會驗證輸入,遇到無效值時會以錯誤結束。
## 搭配 Traefik(反向代理)
```yaml
services:
traefik:
image: traefik:v2.10
command:
- '--providers.docker=true'
- '--entrypoints.web.address=:80'
- '--entrypoints.websecure.address=:443'
- '[email protected]'
- '--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json'
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
ports:
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:latest
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.bentopdf.rule=Host(`pdf.example.com`)'
- 'traefik.http.routers.bentopdf.entrypoints=websecure'
- 'traefik.http.routers.bentopdf.tls.certresolver=letsencrypt'
- 'traefik.http.services.bentopdf.loadbalancer.server.port=8080'
# Required headers for SharedArrayBuffer (LibreOffice WASM)
- 'traefik.http.routers.bentopdf.middlewares=bentopdf-headers'
- 'traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Opener-Policy=same-origin'
- 'traefik.http.middlewares.bentopdf-headers.headers.customresponseheaders.Cross-Origin-Embedder-Policy=require-corp'
restart: unless-stopped
```
## 搭配 Caddy(反向代理)
```yaml
services:
caddy:
image: caddy:2
ports:
- '80:80'
- '443:443'
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:latest
restart: unless-stopped
volumes:
caddy_data:
```
Caddyfile 設定:
```
pdf.example.com {
reverse_proxy bentopdf:8080
header Cross-Origin-Opener-Policy "same-origin"
header Cross-Origin-Embedder-Policy "require-corp"
}
```
## 資源限制
```yaml
services:
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:latest
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
```
## Podman Quadlet(Systemd 整合)
[Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html) 可讓您將 Podman 容器作為 systemd 服務執行。非常適合在 Linux 系統上進行正式環境部署。
### 基本 Quadlet 設定
在 `~/.config/containers/systemd/bentopdf.container`(使用者)或 `/etc/containers/systemd/bentopdf.container`(系統)建立容器單元檔案:
```ini
[Unit]
Description=BentoPDF - Privacy-first PDF toolkit
After=network-online.target
Wants=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf-simple:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
```
### 啟用並啟動
```bash
# Reload systemd to detect new unit
systemctl --user daemon-reload
# Start the service
systemctl --user start bentopdf
# Enable on boot
systemctl --user enable bentopdf
# Check status
systemctl --user status bentopdf
# View logs
journalctl --user -u bentopdf -f
```
> [!TIP]
> 若為全系統部署,請使用不帶 `--user` 旗標的 `systemctl`,並將檔案放在 `/etc/containers/systemd/`。
### 搭配健康檢查的 Quadlet
```ini
[Unit]
Description=BentoPDF with health monitoring
After=network-online.target
Wants=network-online.target
[Container]
Image=ghcr.io/alam00000/bentopdf-simple:latest
ContainerName=bentopdf
PublishPort=3000:8080
AutoUpdate=registry
HealthCmd=wget --spider -q http://localhost:8080 || exit 1
HealthInterval=30s
HealthTimeout=10s
HealthRetries=3
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
```
### 使用 Quadlet 自動更新
有新映像可用時,Podman 可以自動更新容器:
```bash
# Enable auto-update timer
systemctl --user enable --now podman-auto-update.timer
# Check for updates manually
podman auto-update
# Dry run (check without updating)
podman auto-update --dry-run
```
### Quadlet 網路設定
若需自訂網路設定,請建立網路檔案 `bentopdf.network`:
```ini
[Network]
Subnet=10.89.0.0/24
Gateway=10.89.0.1
```
然後在容器檔案中參照它:
```ini
[Container]
Image=ghcr.io/alam00000/bentopdf-simple:latest
ContainerName=bentopdf
PublishPort=3000:8080
Network=bentopdf.network
```
## 更新
```bash
# Pull latest image
docker compose pull
# Recreate container
docker compose up -d
```