Docker

Docker Volume Là Gì? Cách Quản Lý Dữ Liệu Trong Docker Không Lo Mất Khi Xóa Container

phongdhphongdh
14 phút đọc
Chia sẻ:
Zalo
Ảnh đại diện bài Docker Volume là gì - Series Docker cơ bản bài 3 trên phongdinh.info.vn

Ở Bài 1, chúng ta đã thản nhiên docker rm các container sau khi dùng xong. Nhưng hãy tưởng tượng container đó là một database MySQL chứa dữ liệu khách hàng: xóa container là mất sạch dữ liệu. Docker giải quyết bài toán này bằng Volume — vậy Docker Volume là gì, dùng như thế nào và khác gì Bind Mount?

Bài này sẽ thực hành đầy đủ vòng đời của dữ liệu trong Docker: tạo volume, ghi dữ liệu vào, gắn cho web server, rồi cố tình xóa container để chứng minh dữ liệu vẫn còn nguyên. Cuối bài bạn cũng sẽ phân biệt rõ ba cơ chế lưu trữ Volume, Bind Mount và tmpfs để chọn đúng cho từng trường hợp.

Điều kiện thực hành: đã cài Docker và nắm các lệnh chạy container ở Bài 1. Nếu bạn chưa học cách đóng gói ứng dụng, hãy xem thêm Bài 2 về Dockerfile trong series.

1. Docker Volume là gì và vì sao container cần đến nó?

Docker Volume là gì? Đó là một vùng lưu trữ dữ liệu do Docker quản lý, tồn tại độc lập bên ngoài container. Khi container ghi dữ liệu vào một thư mục đã được gắn volume, dữ liệu thực tế nằm ở vùng lưu trữ này chứ không nằm trong lớp ghi (writable layer) của container — nên dù container bị dừng, bị xóa hay được tạo lại từ image mới, dữ liệu trong volume vẫn nguyên vẹn.

Ngược lại, mọi file bạn ghi trực tiếp vào hệ thống file của container (không qua volume) đều nằm trong lớp ghi gắn liền với chính container đó. Lớp này biến mất ngay khi container bị docker rm. Đây là lý do mọi hệ thống chạy bằng Docker — từ WordPress, MySQL đến Seafile như bài cài Seafile bằng Docker trên blog — đều phải gắn volume cho phần dữ liệu quan trọng.

Ngoài Volume, Docker còn hai cơ chế lưu trữ khác. Bind Mount gắn trực tiếp một thư mục có sẵn trên máy chủ vào container — bạn kiểm soát hoàn toàn đường dẫn, tiện cho việc phát triển vì sửa file trên host là container thấy ngay. tmpfs lưu dữ liệu trên RAM của máy chủ, biến mất khi container dừng, chỉ hợp cho dữ liệu tạm hoặc nhạy cảm không muốn ghi xuống đĩa. Ba cơ chế này sẽ lần lượt được thực hành trong bài.

Riêng về Volume còn một phân biệt nhỏ cần biết ngay: named volume là volume bạn đặt tên tường minh (như du-lieu-web sắp tạo) — dễ quản lý, dễ gắn lại cho container sau. Anonymous volume là volume không tên, sinh ra tự động khi image khai báo chỉ thị VOLUME trong Dockerfile hoặc khi bạn gắn volume mà không đặt tên; chúng vẫn bền vững nhưng khó nhận diện và dễ bị bỏ quên, là một trong những nguồn “rác” ta sẽ dọn ở Bài 6.

2. Tạo và quản lý Volume bằng docker volume

Nhóm lệnh docker volume có các lệnh con quen thuộc: create tạo volume, ls liệt kê, inspect xem chi tiết và rm để xóa. Hãy tạo volume đầu tiên tên là du-lieu-web:

Tìm hiểu Docker Volume là gì: tạo volume bằng docker volume create và kiểm tra bằng volume ls, volume inspect

Lệnh create trả về đúng tên volume vừa tạo. Kết quả inspect cho thấy volume dùng driver local — driver mặc định, nghĩa là dữ liệu được lưu trên chính ổ đĩa của máy chủ Docker theo cách Docker tự quản lý vị trí và định dạng. Bạn không cần (và không nên) can thiệp trực tiếp vào thư mục lưu trữ nội bộ này; mọi thao tác đều đi qua container.

Nếu xem bản đầy đủ của docker volume inspect du-lieu-web, bạn sẽ thấy thêm trường Mountpoint — đường dẫn vật lý của volume trên máy chủ, thường có dạng /var/lib/docker/volumes/du-lieu-web/_data. Biết đường dẫn này hữu ích khi cần sao lưu khẩn cấp từ phía host, nhưng hãy nhớ nguyên tắc: chỉ đọc/ghi dữ liệu qua container trong vận hành bình thường, vì Docker không đảm bảo tính nhất quán nếu bạn sửa file trực tiếp trong lúc container đang ghi dữ liệu.

Từ đây có thể thấy rõ hơn Docker Volume là gì ở góc độ quản lý: nó là một đối tượng độc lập do Docker cấp phát và theo dõi, tương tự như image hay container, chứ không phải một thư mục ngẫu nhiên bạn tự tạo trên host.

3. Ghi và đọc dữ liệu qua Volume bằng hai container khác nhau

Thực hành là cách nhanh nhất để hiểu Docker Volume là gì. Để gắn volume vào container, dùng cờ -v <tên-volume>:<đường-dẫn-trong-container> khi docker run. Thử nghiệm kinh điển: một container alpine ghi file vào volume, rồi một container alpine hoàn toàn khác đọc lại file đó:

Ghi file vào Docker Volume bằng một container alpine và đọc lại bằng một container khác

Container thứ nhất ghi dòng chữ “Xin chao Docker Volume” vào file /data/hello.txt rồi thoát và tự xóa (--rm). Container thứ hai — một container mới tinh — gắn cùng volume đó vào đúng thư mục /data và đọc được nguyên văn dòng chữ. Dữ liệu rõ ràng không thuộc về container nào cả; nó thuộc về volume, và container chỉ là “người ghé thăm” dữ liệu mà thôi.

Hai chi tiết cú pháp cần nhớ: dấu hai chấm tách nguồn (tên volume hoặc đường dẫn host) với đích (đường dẫn trong container); và bạn có thể thêm :ro ở cuối để gắn ở chế độ chỉ đọc, container không sửa được dữ liệu — rất hợp cho các file cấu hình hoặc nội dung tĩnh.

4. Chứng minh: xóa container, dữ liệu vẫn còn nguyên

Giờ áp dụng vào tình huống thật. Đầu tiên, “nạp” sẵn một trang web vào volume tên trang-web (dùng container alpine ghi file index.html vào đúng thư mục web của nginx), sau đó chạy container nginx gắn volume đó:

Chạy nginx gắn Volume đã nạp sẵn trang web và kiểm tra kết quả bằng curl

Trang web hiển thị đúng nội dung đã nạp vào volume: “Trang web luu tren Volume”. Bây giờ đến thao tác “phá hoại”: xóa hẳn container web-vol, rồi tạo một container nginx mới tinh tên web-vol2 gắn cùng volume đó:

Xóa container cũ và chạy container mới gắn cùng Volume, trang web vẫn hiển thị nguyên vẹn

Trang web vẫn hiển thị y nguyên dù container cũ đã bị xóa hoàn toàn. Đây chính là minh chứng trực quan nhất cho câu hỏi Docker Volume là gì và vì sao nó quan trọng: vòng đời của dữ liệu đã tách khỏi vòng đời của container. Mọi database chạy bằng Docker (MySQL, PostgreSQL, MongoDB…) đều dựa trên cơ chế này — bạn có thể xóa container database để nâng cấp image mới mà không hề mất dữ liệu.

5. Bind Mount: gắn thư mục thật của máy chủ vào container

Cơ chế thứ hai, Bind Mount, dùng cùng cú pháp -v nhưng vế nguồn là một đường dẫn tuyệt đối trên máy chủ thay vì tên volume. Giả sử trên máy chủ có thư mục /home/phong/site-web chứa sẵn file index.html, hãy gắn nó vào container nginx ở chế độ chỉ đọc:

Gắn thư mục thật trên máy chủ vào container nginx bằng Bind Mount ở chế độ chỉ đọc

Web server đã phục vụ đúng file nằm trên máy chủ. Và đây là “phép màu” khiến Bind Mount được dân lập trình yêu thích: hãy sửa nội dung file ngay trên máy chủ, không đụng gì đến container:

Sửa file index.html ngay trên máy chủ và nội dung web thay đổi lập tức nhờ Bind Mount

Nội dung trang web thay đổi ngay lập tức mà container không cần khởi động lại, vì container và máy chủ đang nhìn vào cùng một file vật lý.

Một lưu ý bảo mật quan trọng của Bind Mount: gắn thư mục hệ thống nhạy cảm của host (ví dụ thư mục gốc hoặc thư mục chứa khóa riêng) vào container đồng nghĩa trao cho container quyền chạm tới chúng — container bị xâm nhập có thể lần ra dữ liệu của máy chủ. Chỉ gắn đúng thư mục ứng dụng cần, ưu tiên chế độ :ro khi container không cần ghi, và tuyệt đối tránh gắn các thư mục hệ thống. Đây là lý do Bind Mount dù tiện cũng cần được dùng có ý thức hơn Volume.

Đây là lý do Bind Mount là lựa chọn số một khi phát triển phần mềm (sửa code trên host, container chạy bản mới nhất), trong khi Volume là lựa chọn đúng cho môi trường production và dữ liệu cần bền vững, vì dữ liệu được Docker quản lý gọn trong “lãnh địa” của nó thay vì phụ thuộc cấu trúc thư mục trên từng máy chủ.

6. tmpfs: lưu dữ liệu trên RAM

Cơ chế cuối cùng, tmpfs, lưu dữ liệu vào bộ nhớ RAM của máy chủ thay vì ổ đĩa. Dữ liệu tmpfs biến mất hoàn toàn khi container dừng, và không bao giờ được ghi xuống đĩa:

docker run -d --name app-tmp --tmpfs /cache nginx
# hoặc dạng --mount đầy đủ:
docker run -d --name app-tmp --mount type=tmpfs,destination=/cache nginx

tmpfs phù hợp cho các file tạm sinh ra trong lúc chạy (cache, file đệm xử lý) hoặc dữ liệu nhạy cảm như khóa bí mật tạm thời — những thứ bạn muốn biến mất sạch sẽ khi container kết thúc và không cần tốc độ đĩa làm nút thắt. Đây cũng là lúc nên biết cú pháp --mount: dài hơn -v nhưng tường minh và ít lỗi hơn, được Docker khuyến nghị cho các kịch bản phức tạp.

Trong thực tế, tmpfs còn là lựa chọn quen thuộc của các hệ thống CI: gắn tmpfs cho thư mục cache hoặc thư mục chứa file tạm của quá trình kiểm thử giúp tốc độ đọc ghi tăng rõ rệt vì không phải chạm vào ổ đĩa vật lý, đồng thời mọi thứ tự biến mất khi job kết thúc mà không cần bước dọn dẹp riêng.

7. Xóa Volume và những lưu ý an toàn

Trước khi xóa, hãy kiểm tra nhanh volume đó đang chứa gì và còn container nào liên quan không: lệnh docker ps -a --filter volume=<tên-volume> liệt kê mọi container (kể cả đã dừng) đang gắn volume này. Nếu danh sách trống và bạn đã chắc chắn dữ liệu không còn cần thiết — hoặc đã sao lưu theo cách ở mục 8 — thì mới tiến hành xóa.

Xóa volume dùng lệnh docker volume rm <tên>.

Docker sẽ từ chối xóa volume đang còn container gắn vào (kể cả container đã dừng) — bạn phải xóa các container đó trước. Sau khi dọn xong hai container demo phía trên, hãy xóa volume du-lieu-web không còn dùng:

Liệt kê các Docker Volume đang có và xóa volume không còn dùng bằng docker volume rm

Đó là toàn bộ vòng đời của một volume, từ lúc tạo đến lúc xóa — phần cốt lõi của câu hỏi Docker Volume là gì. Danh sách cuối còn lại volume trang-web — volume này ta giữ lại vì đang chứa trang web demo.

Ba lưu ý an toàn quan trọng khi xóa volume. Một: xóa volume là mất dữ liệu vĩnh viễn, không có thùng rác như xóa file thường. Hai: các lệnh dọn dẹp hàng loạt như docker volume prune hay docker system prune --volumes (sẽ gặp ở Bài 6) có thể xóa cả volume chứa dữ liệu thật nếu container tham chiếu đã bị xóa trước đó — hãy cực kỳ thận trọng trên server production. Ba: những volume không đặt tên (anonymous volume) sinh ra tự động khi image khai báo chỉ thị VOLUME — chúng tích tụ dần theo thời gian và là đối tượng dọn dẹp thường xuyên.

8. Sao lưu và khôi phục dữ liệu trong Volume

Volume giữ dữ liệu bền vững trước việc xóa container, nhưng nó vẫn nằm trên cùng một ổ đĩa của máy chủ — hỏng đĩa hoặc xóa nhầm volume là mất trắng. Vì vậy dữ liệu quan trọng trong volume vẫn cần được sao lưu định kỳ ra nơi khác. Cách sao lưu phổ biến nhất là dùng một container phụ gắn volume ở chế độ chỉ đọc, nén toàn bộ dữ liệu thành một file tar:

docker run --rm --network none -v trang-web:/data:ro -v /home/phong/backup:/backup alpine tar czf /backup/trang-web-$(date +%F).tar.gz -C /data .

Lệnh trên tạo một file nén chứa toàn bộ nội dung của volume trang-web trong thư mục sao lưu trên máy chủ; từ đây bạn có thể chép file nén sang máy khác hoặc đẩy lên kho lưu trữ đám mây. Khi cần khôi phục vào một volume mới, làm ngược lại: tạo volume trống, rồi dùng container phụ giải nén file tar vào:

docker volume create trang-web-moi
docker run --rm --network none -v trang-web-moi:/data -v /home/phong/backup:/backup:ro alpine sh -c "cd /data && tar xzf /backup/trang-web-2026-10-26.tar.gz"

Một lưu ý quan trọng với dữ liệu database: sao lưu bằng cách nén file như trên chỉ an toàn khi container database đang dừng hoặc không ghi dữ liệu, nếu không các file có thể không nhất quán với nhau. Với hệ thống thật, ưu tiên công cụ sao lưu logic của chính database (như mysqldump hay pg_dump) rồi mới lưu file kết quả vào volume hoặc thư mục sao lưu.

9. Lỗi thường gặp khi dùng Volume và Bind Mount

  • Gắn volume vào là “mất” file gốc của image: khi gắn volume/bind mount vào một thư mục, nội dung volume sẽ che phủ nội dung sẵn có của thư mục đó trong image. Nếu volume rỗng, container sẽ thấy thư mục rỗng — đây là hành vi đúng, không phải lỗi, nhưng rất hay gây hoang mang lần đầu.
  • Chạy database mà quên gắn volume: container MySQL không có -v sẽ lưu dữ liệu vào lớp ghi của container — xóa container là mất toàn bộ dữ liệu. Luôn gắn volume cho thư mục dữ liệu (MySQL: /var/lib/mysql).
  • Bind Mount báo lỗi quyền truy cập: container chạy bằng user khác với chủ sở hữu thư mục trên host nên bị từ chối đọc/ghi. Kiểm tra quyền của thư mục trên host và user bên trong container (chỉ thị USER hoặc cờ --user).
  • Ứng dụng không ghi được file dù đã gắn volume: có thể bạn đã gắn kèm :ro (chỉ đọc), hoặc đường dẫn đích trong container chưa đúng với nơi ứng dụng thực sự ghi dữ liệu.
  • Nhầm Volume với Bind Mount khi chuyển máy: bài viết/code ghi đường dẫn host cụ thể sẽ vỡ khi sang máy khác có cấu trúc thư mục khác. Với ứng dụng triển khai nhiều nơi, ưu tiên Volume (chỉ phụ thuộc tên) hoặc dùng biến môi trường cho đường dẫn.

10. Lời kết

Tóm lại, Docker Volume là gì — đó là cơ chế lưu trữ bền vững do Docker quản lý, giúp dữ liệu sống sót qua mọi lần xóa và tạo lại container; Bind Mount phục vụ nhu cầu gắn thư mục thật của host (tuyệt vời cho lập trình), còn tmpfs lo phần dữ liệu tạm trên RAM. Chọn đúng cơ chế cho đúng loại dữ liệu là kỹ năng nền tảng của mọi hệ thống Docker nghiêm túc.

Bài tiếp theo sẽ chuyển sang khía cạnh kết nối: container giao tiếp với nhau và với bên ngoài bằng cách nào — đó là chủ đề Docker Network, Bài 4 của series Docker cơ bản.

Chia sẻ bài viết này:
Zalo
phongdh

phongdh

Tác giả bài viết • Content Creator

Chào mọi người, mình là Phong - hiện đang công tác tại Phòng Kỹ thuật AZDIGI. Trong quá trình làm việc mình có cơ hội được tiếp xúc với khá nhiều các vấn đề liên quan đến Website/Email/Hosting/VPS/Server, do đó mình viết lại các hướng dẫn này nhằm chia sẻ kiến thức, cũng như tạo một môi trường để chúng ta giao lưu và học hỏi lẫn nhau.

Kết nối:

Bài viết liên quan

Những bài viết bạn có thể quan tâm

Thảo luận 0 bình luận Viết bình luận

Email được bảo mật và không hiển thị công khai.

Chưa có bình luận. Hãy là người mở đầu cuộc trò chuyện.

Zalo