SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-21

Nextcloud Docker lưu file ở đâu? Tìm volume trên host

Tìm đúng data directory trong container, đường dẫn volume trên host và 3 volume cần backup để khôi phục Nextcloud, không chỉ chép file người dùng.

Nextcloud trong Docker lưu file ở đâu

Nextcloud trong Docker lưu file trong một thư mục dữ liệu bên trong container. Vị trí thực trên server là volume hoặc bind mount mà bạn gắn vào container. Với image linuxserver.io, lscr.io/linuxserver/nextcloud, file của người dùng nằm ở /data. Bản cài đặt Nextcloud cùng với config.php nằm ở /config. Cả hai đều là đường dẫn bên trong container. Một command sẽ in ra đường dẫn trên host tương ứng với các đường dẫn đó. Phần còn lại của hướng dẫn này giải thích nửa khó hơn của câu hỏi: những thứ mà thư mục dữ liệu không chứa.

Cố định image tag. Đường dẫn phụ thuộc vào image, không phải bản thân Nextcloud, và một tag không cố định có thể thay đổi mà bạn không nhận ra. Tính đến August 2026, stable tag hiện tại của image này là 34.0.3.

services:
  nextcloud:
    image: lscr.io/linuxserver/nextcloud:34.0.3
    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:

Hai password được lấy từ file .env nằm cạnh compose file, nên không nằm trực tiếp trong compose file. Như vậy có 3 volume trong câu trả lời, nhưng chỉ 1 volume chứa file của người dùng.

Các đường dẫn bên trong container này được lấy từ tài liệu của image đó. Image Nextcloud khác có thể bố trí filesystem khác và đặt bản cài đặt dưới web root riêng. Vì vậy, đường dẫn chép từ một bài đăng trên forum chỉ là phỏng đoán. Hãy đọc thông tin chính xác từ container mà bạn đang chạy.

docker inspect nextcloud

Phần Mounts trong output liệt kê mọi mount, với Source ở phía host và Destination ở phía container. Danh sách này trả lời chính xác câu hỏi cho hệ thống của bạn, bất kể bạn chọn image nào.

Làm thế nào để tìm đường dẫn thật trên host phía sau volume?

Named volume do Docker quản lý, nên bạn không tự chọn đường dẫn của nó. Hãy yêu cầu Docker trả về đường dẫn đó.

docker volume ls
docker volume inspect nextcloud_nextcloud_data

Tên volume rất quan trọng. Docker Compose thêm tiền tố tên project vào tên volume. Mặc định, tên project là tên thư mục chứa compose file. Vì vậy, volume được ghi là nextcloud_data trong file thường tồn tại trên disk với tên nextcloud_nextcloud_data. docker volume ls hiển thị các tên thật. Kết quả inspect được rút gọn sẽ có dạng sau:

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

Mountpoint là câu trả lời. Hãy đọc giá trị này từ command thay vì tự đoán, vì đường dẫn có thể thay đổi. Với rootless Docker, toàn bộ Docker data root nằm trong home directory của user chạy daemon, nên đường dẫn đó sẽ bắt đầu từ một vị trí khác.

Bind mount loại bỏ câu hỏi này. Ghi - /srv/nextcloud/data:/data trong compose file. Khi đó, host path chính là đường dẫn bạn đã nhập. docker inspect báo cáo đường dẫn đó là Source. Lựa chọn này không chỉ thay đổi đường dẫn, vì named volume và bind mount hoạt động khác nhau về ownership và backup.

Vì sao data directory không phải là backup

Tài liệu Nextcloud liệt kê 5 thành phần mà một bản backup phải giữ: thư mục config, thư mục custom apps, thư mục data, thư mục theme và database. Với image này, các thư mục config, apps và theme đều nằm dưới /config, còn database chạy trong container riêng với volume riêng. Chỉ sao chép /data thì bạn mới lưu được phần ít quan trọng nhất của vấn đề.

Database rất quan trọng vì giao diện web không liệt kê trực tiếp các directory. Nó liệt kê các row từ file cache. Vì vậy, tài liệu yêu cầu bạn chạy scan sau khi chép file thủ công vào data directory. Khôi phục /data bên cạnh một database trống thì bạn chỉ có các byte nhưng không có index: không có user, share và không có file nào trong danh sách. Khôi phục database bên cạnh một /data trống thì mọi row đều trỏ đến file đã biến mất.

config.php chứa credential của database và trusted domain. Nó cũng chứa instance ID, là tên của app data folder bên trong data directory. Hãy hỏi instance đang chạy thay vì tin vào một trong hai giá trị này từ trí nhớ.

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

Lệnh đầu tiên in ra data directory mà instance này thực sự sử dụng. Ở đây, directory đó là /data. Image này cung cấp một wrapper occ trong PATH, vì vậy hãy chạy trực tiếp qua docker exec. Không sao chép dạng dài hơn sudophp occ từ tài liệu Nextcloud. Dạng đó dành cho installation chạy ngoài container.

Điều gì đang âm thầm chiếm đầy data volume?

Preview và lịch sử theo từng user nằm cùng volume với các file, nhưng cả hai đều không được tính trong thông tin dung lượng mà user thấy trên web interface.

  • Preview là các thumbnail được tạo tự động. Chúng nằm trong thư mục app data bên trong data directory, có tên là appdata_ theo sau bởi instance id.
  • File đã xóa vẫn nằm trong trash. trashbin_retention_obligation mặc định là auto, giữ file trong 30 ngày và chỉ xóa sau thời gian đó khi cần thêm dung lượng. File đã xóa vẫn được tính vào quota của user. Khi vượt quota, thiết lập thời gian lưu sẽ bị bỏ qua và trash được dọn cho đến khi quota vừa lại.
  • Phiên bản cũ cũng được giữ lại. versions_retention_obligation cũng mặc định là auto. Ứng dụng Versions không bao giờ dùng quá 50% dung lượng hiện còn trống của user. Khi dọn, ứng dụng xóa phiên bản cũ nhất trước và giữ lại 2 phiên bản gần nhất. Phiên bản do user đặt tên thủ công sẽ không bao giờ bị xóa.

Hãy đo dung lượng trước khi xóa bất kỳ thứ gì.

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

Dòng đầu tiên cho biết một số liệu cho mỗi thư mục user và một số liệu cho app data folder. Nếu số liệu của app data lớn, nguyên nhân là preview. Các lệnh dọn dẹp bên dưới đã được ghi chép. Mỗi lệnh đều chủ động xóa data.

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 xóa mọi preview đã tạo. Nextcloud sẽ tạo lại chúng khi user mở các file đó, nên dung lượng sẽ dần tăng lại và CPU sẽ phải xử lý việc này. Nếu volume chỉ là một phần của vấn đề disk rộng hơn, image cũ và build cache không còn dùng thường là phần còn lại.

Vì sao các file tôi copy vào host lại không xuất hiện trong Nextcloud?

Vì Nextcloud đọc cache file trong database, không đọc trực tiếp thư mục. Lệnh copy của bạn đã tạo file trên disk nhưng không có row tương ứng trong database, nên giao diện web không có gì để liệt kê. Tài liệu hướng dẫn nêu đúng trường hợp này: cần chạy scan sau khi copy file trực tiếp vào data directory.

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

Đối số --path cũng cho thấy cấu trúc bên trong data directory: mỗi user có một thư mục mang username của họ, và files bên trong thư mục đó chứa những gì họ thấy trên giao diện web. Chạy scan trên một path khi bạn biết file đã được copy vào đâu. --all quét tất cả user và sẽ mất nhiều thời gian trên instance lớn. --unscanned chỉ xử lý các file được đánh dấu là chưa scan đầy đủ. -v in từng file khi xử lý; nhờ đó bạn phân biệt được một command thực sự bị treo với command mà bạn có thể theo dõi.

Ownership quyết định scan có đủ hay không. File mà container user không thể ghi sẽ được index, nhưng sau đó không thể move. Vì vậy listing vẫn hiển thị đúng, trong khi thao tác rename hoặc delete trên giao diện web lại thất bại.

Vì sao thao tác ghi vẫn thất bại sau khi tôi đặt PUID và PGID?

Vì kernel so sánh các giá trị số, không so sánh tên. PUID và PGID đặt user id (uid) và group id (gid) dạng số mà process trong container sử dụng. Mỗi file trên host cũng có owner dạng số. Khi hai giá trị này khác nhau, thao tác ghi sẽ bị từ chối, dù tên ở hai phía trông giống nhau.

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

id abc in ra uid và gid mà container thực sự sử dụng. Đây là các giá trị PUID và PGID bạn đã đặt. ls -ln in ra owner dạng số, còn -n rất quan trọng: ls -l thông thường chuyển các giá trị đó qua danh sách user của host và hiển thị một tên không có ý nghĩa bên trong container. Hãy so sánh hai giá trị số.

Sau đó, hãy kiểm tra thao tác ghi thay vì đoán.

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

Một Permission denied có tên /data là bằng chứng xác nhận. Hãy sửa ownership từ bên trong container, rồi chạy lại cùng bài kiểm tra.

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

Có lý do để thực hiện việc này từ bên trong container. Với rootless Docker, user id của container được ánh xạ qua dải subordinate trong /etc/subuid, nên uid 1000 bên trong container tương ứng với một uid cao hơn nhiều trên host. Khi đó, chown 1000:1000 chạy trên host sẽ đặt owner mà container không thể sử dụng, và thao tác ghi vẫn thất bại. Chạy chown bên trong container sử dụng cùng mapping mà process Nextcloud sử dụng, nên các giá trị số tự khớp với nhau. Đây cũng là lý do PUID và PGID phải khớp với owner trên disk trước khi bạn bắt đầu debug các vấn đề khác.

Cách backup để restore thực sự hoạt động?

Lấy database và các thư mục tại cùng một thời điểm. Maintenance mode chặn đăng nhập, nên không có file upload nào được ghi thêm giữa lúc dump và lúc copy.

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

Lưu ý dòng dump không có gì: không có flag -t. TTY sẽ viết lại ký tự xuống dòng. SQL dump đã đi qua TTY có thể bị hỏng, nhưng chỉ phát hiện được khi restore. Cũng lưu ý rằng password trên command line sẽ hiện trong output của ps khi command đang chạy. Vì vậy, hãy đọc password từ file .env vào shell thay vì gõ trực tiếp. Các database image cũ dùng mysqldump thay cho mariadb-dump. Manual có tài liệu cho cả hai.

Để restore, hãy nạp dump vào một database trống, giải nén cả hai archive vào các volume mới, khởi động các container, rồi tắt maintenance mode. Nếu các thư mục và dump được tạo ở những thời điểm khác nhau, file cache và dữ liệu trên disk sẽ không khớp. occ files:scan --all chỉ sửa được một chiều. Nó tìm các file đang tồn tại nhưng không có row tương ứng. Nó không thể khôi phục file mà một row đang trỏ tới.

Lưu bản backup bên ngoài server. Bản copy nằm trong cùng VPS sẽ mất cùng VPS. Vì vậy, restic đến repository bên ngoài server cần nằm trong quy trình này. Snapshot của provider là công cụ khác với backup. Nếu bạn vẫn đang dựng stack, Cài đặt Nextcloud đầy đủ trên VPS có hướng dẫn về reverse proxy và certificate TLS (transport layer security) mà guide này không đề cập.

FAQ

Thư mục data của Nextcloud nằm ở đâu trong Docker container?

Với image linuxserver.io, thư mục này là /data bên trong container, còn bản cài đặt bằng config.php nằm tại /config. Đây là các path trong container. Để biết path trên host, chạy docker inspect nextcloud rồi đọc giá trị Source trong phần Mounts, hoặc chạy docker volume inspect trên volume rồi đọc Mountpoint. Các image Nextcloud khác dùng path trong container khác, vì vậy hãy kiểm tra documentation của tag bạn đã pin và xác nhận bằng docker exec -it nextcloud occ config:system:get datadirectory.

Vì sao các file tôi copy vào volume không xuất hiện trong Nextcloud?

Nextcloud lấy danh sách các dòng từ file cache trong database thay vì đọc trực tiếp directory. Vì vậy, file được đưa vào mà không đi qua Nextcloud sẽ không có dòng tương ứng và vẫn bị ẩn. Chạy docker exec -it nextcloud occ files:scan --path="/alice/files/Photos" cho một folder hoặc occ files:scan --all cho tất cả user. Nếu file xuất hiện nhưng sau đó không thể move hoặc delete, nguyên nhân là ownership: user của container phải có quyền write vào các file đó.

Chỉ copy data volume có đủ để restore Nextcloud không?

Không. Data volume chứa nội dung file. Database chứa file index cùng với user và share, còn config.php chứa database credentials và instance id. Một lần restore đầy đủ cần data folder, config folder, database, cùng các custom app và theme folder nếu bạn sử dụng chúng. Hãy lấy tất cả từ cùng một thời điểm, vì database mới hơn các file sẽ trỏ đến những file không tồn tại.

Vì sao data volume lớn hơn nhiều so với các file mà user nhìn thấy?

Preview, file đã xóa và version cũ nằm trong cùng volume, nhưng không mục nào xuất hiện trong dung lượng mà user nhìn thấy. Đo dung lượng bằng docker exec -it nextcloud sh -c 'du -sh /data/*'. Trash giữ file đã xóa trong 30 ngày theo mặc định và chỉ xóa sớm hơn khi cần chỗ trống. Ứng dụng Versions có thể dùng tối đa một nửa dung lượng trống hiện có của user. Xóa chúng bằng occ trashbin:cleanup --all-users, occ versions:cleanup aliceocc preview:cleanup, đồng thời dự kiến preview sẽ tăng trở lại khi user mở file.

Có thể chuyển thư mục data của Nextcloud sang disk khác không?

Mount vị trí mới vào cùng path trong container thay vì thay đổi path mà Nextcloud đang biết. Stop container, copy toàn bộ nội dung cũ sang disk mới và giữ nguyên ownership (cp -a hoặc rsync -aAX), trỏ volume hoặc bind mount đến vị trí mới trong file compose, rồi start lại container. Nextcloud vẫn thấy /data, nên không cần thay đổi dòng nào trong database. Xác minh bằng docker exec -it nextcloud occ config:system:get datadirectory và một lần upload thử.