SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor

Nextcloud Docker 檔案儲存位置與備份指南

解析 Nextcloud 在 Docker 容器內的資料目錄路徑,並說明如何透過 docker inspect 查詢宿主機掛載點。本指南涵蓋具名 Volume 與 Bind mount 的差異,確保您能完整備份資料庫與設定檔,而非僅複製使用者檔案。

Nextcloud in Docker 儲存檔案的位置

Nextcloud in Docker 會將檔案儲存在容器內的資料目錄,而伺服器上的實際位置則取決於你附加的 volume 或 bind mount。使用 linuxserver.io image 時,lscr.io/linuxserver/nextcloud、使用者檔案位於 /data,Nextcloud 安裝內容及其 config.php 則位於 /config。這兩個都是容器路徑。執行一個指令即可列出它們對應的主機路徑。本指南其餘內容將處理這個問題較困難的部分:資料目錄未包含的所有內容。

固定 image tag。路徑隸屬於 image,而不是 Nextcloud;浮動 tag 可能在你未注意時變更。截至 October 20, 2026,此 image 的目前 stable tag 是 35.0.2,也是 Nextcloud 35 major version 的第 3 個 release。此 image 一次只升級 1 個 major version,因此仍在 34.x 的 stack 會分 1 個步驟升級至 35,而且執行這個步驟前應先備份。

services:
  nextcloud:
    image: lscr.io/linuxserver/nextcloud:35.0.2
    container_name: nextcloud
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - nextcloud_config:/config
      - nextcloud_data:/data
    ports:
      - 443:443
    restart: unless-stopped

  nextcloud-db:
    image: mariadb:11.8
    container_name: nextcloud-db
    environment:
      - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
      - MARIADB_DATABASE=nextcloud
      - MARIADB_USER=nextcloud
      - MARIADB_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
    volumes:
      - nextcloud_db:/var/lib/mysql
    restart: unless-stopped

volumes:
  nextcloud_config:
  nextcloud_data:
  nextcloud_db:

這 2 個密碼來自 compose file 旁的 .env 檔案,因此不會留在 compose file 本身。答案中共有 3 個 volume,其中只有 1 個儲存使用者檔案。

上述容器路徑來自該 image 的文件。其他 Nextcloud image 的檔案系統配置可能不同,並會將安裝內容放在自己的 web root 下,因此從論壇文章複製路徑只是猜測。請直接從正在執行的容器中確認實際資訊。

docker inspect nextcloud

該輸出的 Mounts 區段會列出每個 mount,其中 Source 是主機端,Destination 是容器端。無論選用哪個 image,這份清單都能回答你目前設定中的路徑問題。

如何找出 Volume 背後的實際主機路徑?

具名 Volume 由 Docker 管理,因此您無法自行指定路徑,必須透過查詢取得。

docker volume ls
docker volume inspect nextcloud_nextcloud_data

名稱至關重要。Docker Compose 會在 Volume 名稱前加上專案名稱(預設為包含 compose 檔案的目錄名稱),因此在檔案中寫為 nextcloud_data 的 Volume,在磁碟上通常會以 nextcloud_nextcloud_data 存在。docker volume ls 可顯示實際名稱。inspect 的輸出結果如下(已刪減):

[
    {
        "CreatedAt": "2026-08-18T09:12:44Z",
        "Driver": "local",
        "Mountpoint": "/var/lib/docker/volumes/nextcloud_nextcloud_data/_data",
        "Name": "nextcloud_nextcloud_data",
        "Scope": "local"
    }
]

Mountpoint 即為答案。請直接從指令讀取,不要預設路徑,因為它可能會變動。在 rootless Docker 下,整個 Docker 資料根目錄位於執行 daemon 的使用者家目錄內,因此該路徑會從其他位置開始。

使用 Bind mount 則無此問題。在 compose 檔案中寫入 - /srv/nextcloud/data:/data,主機路徑即為您輸入的路徑,docker inspect 會將其回報為 Source。此選擇不僅影響路徑,因為 具名 Volume 與 Bind mount 在擁有權與備份處理上的行為有所不同。

為何資料目錄不等於備份

Nextcloud 手冊列出了備份必須包含的五個項目:設定檔資料夾、自訂應用程式資料夾、資料目錄、佈景主題資料夾以及資料庫。在此映像檔中,設定檔、應用程式與佈景主題資料夾皆位於 /config 下,而資料庫則在各自的容器中運行並擁有獨立的 volume。若僅複製 /data,您只保存了問題中最不重要的一部分。

資料庫至關重要,因為網頁介面並非直接列出目錄內容,而是列出檔案快取中的資料列;這也是為何手冊要求在手動複製檔案至資料目錄後,必須執行掃描的原因。若將 /data 還原至一個空的資料庫,您將得到一堆沒有索引的位元組:沒有使用者、沒有分享連結,檔案清單中空無一物。反之,若將資料庫還原至一個空的 /data,則每一筆資料列都會指向不存在的檔案。

config.php 存放了資料庫憑證與信任網域。它同時也存放了 instance id,這正是資料目錄內應用程式資料夾的名稱。請直接詢問正在執行的實例,不要憑記憶使用任何數值。

docker exec -it nextcloud occ config:system:get datadirectory
docker exec -it nextcloud occ config:system:get instanceid

第一行指令會印出此實例實際使用的資料目錄,在此處為 /data。此映像檔在路徑中內建了 occ 包裝器,因此請直接透過 docker exec 執行。請勿複製 Nextcloud 手冊中較長的 sudo 與 php occ 格式,該格式是針對容器外安裝環境所撰寫的。

什麼在悄悄填滿資料磁碟區?

預覽檔與每位使用者的歷程記錄,和檔案位於同一個磁碟區中,但兩者都不會顯示在使用者於 Web 介面看到的儲存空間用量中。

  • 預覽檔是自動產生的縮圖。它們位於資料目錄內的應用程式資料資料夾中,名稱以 appdata_ 開頭,後面接著執行個體 ID。
  • 刪除的檔案會留在垃圾桶中。trashbin_retention_obligation 預設為 auto,會保留檔案 30 days,之後只有在需要空間時才會刪除。刪除的檔案不會計入使用者的一般配額,但垃圾桶有自己的限制:預設最多使用該使用者剩餘配額空間的 50%,沒有配額的使用者則受可用磁碟空間限制。垃圾桶超過該限制時,Nextcloud 會先移除符合條件的最舊項目;仍在 30 days 保留期間內的項目不會被移除。
  • 舊版本也會保留。versions_retention_obligation 同樣預設為 auto,會隨時間逐步減少版本數量,並在每個時間區段保留最新版本;背景工作則會移除超過保留期限的版本,或檔案已不存在的版本。Versions 應用程式不會使用超過使用者目前可用空間 50% 的容量。需要釋放空間時,會先刪除最舊的版本,但至少保留最近的 2 個版本。使用者手動命名的版本不會納入自動到期刪除,但使用者仍可手動刪除該版本,而 occ versions:cleanup 會連同其他版本一起移除已命名的版本。

刪除任何項目前,先測量用量。

docker exec -it nextcloud sh -c 'du -sh /data/*'
docker exec -it nextcloud sh -c 'du -sh /data/appdata_*'

第一行會列出每個使用者資料夾及應用程式資料資料夾各自的數值。如果應用程式資料的數值很大,原因就是預覽檔。以下清理指令都有文件說明,而且每一個指令都會刻意刪除資料。

docker exec -it nextcloud occ trashbin:cleanup --all-users
docker exec -it nextcloud occ versions:cleanup alice
docker exec -it nextcloud occ preview:cleanup

preview:cleanup 會移除所有產生的預覽檔。使用者開啟檔案時,Nextcloud 會再次產生這些預覽檔,因此空間會逐漸被重新占用,CPU 也需要處理相應工作。如果磁碟區只是更大範圍磁碟問題的一部分,舊映像檔與過時的建置快取 通常是另一個原因。

為什麼我複製到主機的檔案沒有出現在 Nextcloud 中?

因為 Nextcloud 是讀取資料庫中的檔案快取,而非直接讀取目錄。您直接複製檔案到磁碟時,資料庫中並無對應的記錄,因此網頁介面無法列出這些檔案。手冊中明確提到了這種情況:將檔案直接複製到資料目錄後,必須執行掃描。

docker exec -it nextcloud occ files:scan --path="/alice/files/Photos"
docker exec -it nextcloud occ files:scan --unscanned -v
docker exec -it nextcloud occ files:scan --all

--path 參數也能顯示資料目錄內的配置:每個使用者都有一個以其帳號命名的資料夾,而其中的 files 存放著網頁介面上所見的內容。若您知道檔案存放的位置,請掃描該路徑。--all 會遍歷所有使用者,在大型執行個體上會耗費很長時間。--unscanned 僅處理尚未完全掃描的檔案。-v 會在處理每個檔案時進行輸出,這能讓您區分指令是卡住還是正在運作中。

檔案擁有權決定了掃描是否足夠。若容器使用者無法寫入該檔案,系統在索引後將無法移動它,這會導致檔案列表看起來正常,但從網頁介面進行重新命名或刪除時會失敗。

為什麼設定 PUID 和 PGID 後寫入會失敗?

因為核心比對的是數字,而非名稱。PUID 和 PGID 設定了容器處理程序執行時所使用的數值使用者 ID (uid) 與群組 ID (gid)。主機上的每個檔案也都帶有數值擁有者。當這兩個數字不一致時,寫入就會被拒絕,無論兩端的名稱看起來為何。

docker exec -it nextcloud id abc
sudo ls -ln /var/lib/docker/volumes/nextcloud_nextcloud_data/_data

id abc 會印出容器實際使用的 uid 與 gid,也就是您設定的 PUID 與 PGID。ls -ln 會印出數值擁有者,而 -n 很重要:單純的 ls -l 會透過主機自身的使用者列表轉換這些數字,並顯示一個在容器內部毫無意義的名稱。請比對這兩個數字。

接著請直接測試寫入,不要憑空猜測。

docker exec -u abc -it nextcloud touch /data/writetest

使用 Permission denied 指定 /data 進行測試即可確認。請從容器內部修正擁有權,然後再次執行相同的測試。

docker exec -u 0 -it nextcloud chown -R abc:abc /data
docker exec -u abc -it nextcloud touch /data/writetest
docker exec -u abc -it nextcloud rm /data/writetest

從內部執行是有原因的。在 rootless Docker 下,容器的使用者 ID 會透過 /etc/subuid 中的從屬範圍進行映射,因此容器內的 uid 1000 在主機上對應的是一個更大的 uid。此時若在主機端執行 chown 1000:1000,會設定一個容器無法使用的擁有者,導致寫入依然失敗。在容器內部執行 chown 會經過與 Nextcloud 處理程序本身相同的映射機制,因此數字會自動對齊。這也是為什麼在開始進行任何其他除錯前,PUID 和 PGID 必須與磁碟上的擁有者相符 的原因。

如何確保備份在還原時確實有效?

請在同一時間點取得資料庫備份與檔案目錄。維護模式(maintenance mode)會停止登入,確保在執行資料庫傾印(dump)與檔案複製期間,不會有新的上傳資料寫入。

docker exec -it nextcloud occ maintenance:mode --on
docker exec nextcloud-db mariadb-dump --single-transaction -u nextcloud -p"$NEXTCLOUD_DB_PASSWORD" nextcloud > nextcloud-sqlbkp.sql
docker run --rm -v nextcloud_nextcloud_data:/data:ro -v "$PWD":/backup alpine:3.22 tar czf /backup/nextcloud-data.tgz -C /data .
docker run --rm -v nextcloud_nextcloud_config:/config:ro -v "$PWD":/backup alpine:3.22 tar czf /backup/nextcloud-config.tgz -C /config .
docker exec -it nextcloud occ maintenance:mode --off

請注意傾印指令中缺少了 -t 旗標。TTY 會重寫換行符號,若 SQL 傾印檔經過此處理將會損毀,且該問題通常僅在還原時才會發現。此外,請注意在指令列輸入密碼會顯示於 ps 輸出中,因此建議從 .env 檔案讀取密碼並傳入 shell,而非直接輸入。舊版的資料庫映像檔使用 mysqldump 而非 mariadb-dump,相關說明請參閱手冊。

還原時,請將傾印檔載入至空的資料庫,將兩個封存檔解壓縮至全新的儲存空間,啟動容器,最後關閉維護模式。若檔案目錄與資料庫傾印的時間點不一致,檔案快取與磁碟內容將會衝突,而 occ files:scan --all 僅能修復單一方向的錯誤。它能找出存在但無對應資料列的檔案,但無法找回資料列指向但已遺失的檔案。

請將備份結果存放在伺服器外部。存放在同一台 VPS 內的備份會隨該 VPS 一同損毀,這就是為什麼 使用 restic 備份至外部儲存庫 是此流程的必要環節,也是為什麼 供應商快照與備份是不同的工具。若您仍在建構服務堆疊,在 VPS 上完整安裝 Nextcloud 一文涵蓋了本指南未提及的反向代理與 TLS (transport layer security) 憑證設定。

FAQ

Nextcloud Docker 容器中的資料目錄在哪裡?

使用 linuxserver.io 映像時,資料目錄位於容器內的 /data,而使用 config.php 安裝的內容位於 /config。這些都是容器內的路徑。若要找出主機上的路徑,請執行 docker inspect nextcloud,讀取 Mounts 區段中的 Source 值;或在該 volume 上執行 docker volume inspect,讀取 Mountpoint。其他 Nextcloud 映像可能使用不同的容器路徑,因此請查閱所固定 tag 的說明文件,並使用 docker exec -it nextcloud occ config:system:get datadirectory 確認。

為什麼我複製到 volume 的檔案沒有出現在 Nextcloud 中?

Nextcloud 會從資料庫中的檔案快取列出檔案,而不是直接讀取目錄。因此,未經 Nextcloud 處理而加入的檔案沒有對應資料列,會維持不可見。請針對單一資料夾執行 docker exec -it nextcloud occ files:scan --path="/alice/files/Photos",或針對所有使用者執行 occ files:scan --all。如果檔案會出現,但之後無法移動或刪除,原因是擁有者設定錯誤:容器使用者必須具備寫入這些檔案的權限。

只複製資料 volume 就足以還原 Nextcloud 嗎?

不夠。資料 volume 只包含檔案內容。資料庫則包含檔案索引、使用者與分享資訊,而 config.php 包含資料庫認證資訊與 instance id。要成功還原,必須備份資料資料夾、設定資料夾、資料庫,以及使用中的自訂 apps 和佈景主題資料夾。所有內容都必須取自同一時間點,因為資料庫若比檔案新,就可能指向不存在的檔案。

為什麼我的資料 volume 遠大於使用者看得到的檔案?

預覽、已刪除檔案與舊版本都存放在同一個 volume 中,但這些內容不會顯示在使用者看到的容量數字中。請使用 docker exec -it nextcloud sh -c 'du -sh /data/*' 測量。依預設,垃圾桶至少會保留已刪除檔案 30 days,之後只有在需要空間時才會移除;Versions app 則可能使用使用者目前可用空間的一半。請使用 occ trashbin:cleanup --all-users、occ versions:cleanup alice 與 occ preview:cleanup 清理這些內容,並預期使用者開啟檔案後,預覽會再次增加。

可以將 Nextcloud 資料目錄移到其他磁碟嗎?

請將新位置掛載到相同的容器路徑,不要變更 Nextcloud 已知的路徑。先停止容器,再以保留擁有者資訊的方式將舊內容複製到新磁碟(cp -a 或 rsync -aAX),接著在 compose 檔案中將 volume 或 bind mount 指向新位置,最後重新啟動容器。Nextcloud 仍會看到 /data,因此不需要變更資料庫中的任何資料列。請使用 docker exec -it nextcloud occ config:system:get datadirectory 驗證,並執行一次測試上傳。