Sử dụng Liên kết Volume trong Docker

Volume là cơ chế được khuyến nghị để lưu tồn các dữ liệu được tạo ra và sử dụng bởi Docker container. Không giống như trùng kết bị phụ thuộc vào file-system của máy host, các volume được điều khiển hoàn toàn bởi Docker và qua đó đạt được một số lợi thế:

  • Dễ backup hơn.
  • Có thể được quản lý thông qua Docker CLI hay Docker API.
  • Hoạt động tốt trên cả container Linux lẫn Windows.
  • Có thể được chia sẻ một cách an toàn giữa nhiều container.
  • Cho phép đặt volume remote (trong một máy host hay trong một cloud); cho phép mã hóa; và cho phép bổ sung chức năng.
  • Volume mới có thể có dữ liệu được chuẩn bị trước bởi container.

Thêm nữa, volume là lựa chọn tốt hơn so với lưu tồn dữ liệu trực tiếp trong các writable layer của container; volume không làm tăng dung lượng của container, và volume sẽ giúp lưu chứa những nội dung nằm ngoài vòng đời của container.

Ba cơ chế mount

Nếu container tạo ra những dữ liệu không cần lưu tồn, nên cân nhắc sử dụng một phép tmpfs mount để tránh ghi trực tiếp, làm tăng dung lượng và giảm hiệu năng của container.

Dẫn Kết của liên kết volume được đặt là rprivate, và không cấu hình được.

Khai báo --volume và khai báo --mount

Về cơ bản, để thực hiện thao tác mount (nôm na là liên kết, kết, hay “cắm”) một file-system vào container, sẽ cần tới bộ các thông tin sau:

  • Cơ chế liên kết (bind, volume hay tmpfs).
  • Nguồn liên kết. Với cơ chế bind thì nguồn chính là thư mục ở file-system của máy host. Với cơ chế volume thì nguồn là tên volume.
  • Mục tiêu. Là vị trí (đường dẫn) để cắm tập tin hay thư mục vào file-system của container.
  • Có tạo liên kết chỉ-đọc không.
  • Các cấu hình khác.

Để gọi một phép kết có thể sử dụng cờ --mount hoặc cờ -v hay --volume, khác nhau cơ bản là ở cách mô tả các thông tin về liên kết. Trong khi --mount tách biệt các thông tin liên kết và yêu cầu chỉ thị tên của từng thông tin một, --volume nhận tất cả các thông tin còn lại trong một chuỗi đầu vào duy nhất, gồm ba phần cách nhau bởi ký tự :, và qua đó nội suy từng thông tin. Chi tiết về các phần trong đầu vào như sau:

  • Phần đầu là nguồn liên kết, có thể là volume, hay tập tin/thư mục trên máy host.
  • Phần giữa là mục tiêu liên kết, là đường dẫn của tập tin hay thư mục trong container.
  • Phần cuối là tập các cấu hình, trong đó có cả cấu hình về tính chỉ-đọc, được phân biệt với nhau bởi dấu phẩy.

--volume ngắn gọn hơn, nhưng không tường minh bằng --mount. Thêm nữa, --mount khả dụng với swarm mode, còn --volume thì không. Do đó --mount là cách duy nhất khả dụng khi sử dụng docker service.

Tạo và quản lý volume

Volume có thể được tạo ra trước khi được liên kết vào bất kỳ container nào:

docker volume create my-vol

Xuất danh sách các volume:

$ docker volume ls
local               my-vol

Inspect một volume:

$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

Xóa bỏ:

$ docker volume rm my-vol

Khởi động container với volume

Khai báo liên kết với volume được thực hiện khi chạy docker run. Nếu volume không tồn tại sẵn thì Docker Engine sẽ tạo volume mới.

Sử dụng --mount:

$ docker run -d \
  --name devtest \
  --mount source=myvol2,target=/app \
  nginx:latest

Sử dụng --volume:

$ docker run -d \
  --name devtest \
  -v myvol2:/app \
  nginx:latest

Inspect volume devtest, tìm tới mục Mounts và xác nhận volume đã được liên kết:

"Mounts": [
    {
        "Type": "volume",
        "Name": "myvol2",
        "Source": "/var/lib/docker/volumes/myvol2/_data",
        "Destination": "/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

Thông tin cho thấy một volume đang được liên kết, nguồn và đích đã chính xác, đây là liên kết đọc-ghi.

Dừng container, sau đó xóa container và volume, lưu ý rằng xóa volume là một thao tác riêng biệt.

$ docker container stop devtest
$ docker container rm devtest
$ docker volume rm myvol2

Dùng container để trải dữ liệu cho volume

Khi khởi động container, nếu volume liên kết không tồn tại trước đó, thì nội dung đích sẽ được sao chép vào volume. Sau đó volume mới được liên kết và sử dụng.

Ví dụ dưới đây khởi động container nginx và trải dữ liệu của thư mục /usr/share/nginx/html (nơi mà nginx chứa nội dung phục vụ mặc định) vào volume nginx-vol.

Sử dụng --mount:

$ docker run -d \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html \
  nginx:latest

Sử dụng --volume:

$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html \
  nginx:latest

Liên kết chỉ-đọc

Với một số ứng dụng, container cần ghi dữ liệu vào nguồn liên kết và nhờ đó dữ liệu được chuyển sang máy host. Với một số ứng dụng khác, container chỉ có nhu cầu đọc. Và khi đó nên sử dụng cấu hình ro để tạo một liên kết chỉ-đọc.

Sử dụng --mount:

$ docker run -d \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
  nginx:latest

Sử dụng --volume:

$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest

Inspect container để xác nhận volume đã được liên kết chỉ-đọc:

"Mounts": [
    {
        "Type": "volume",
        "Name": "nginx-vol",
        "Source": "/var/lib/docker/volumes/nginx-vol/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": false,
        "Propagation": ""
    }
],

Lưu ý, một volume có thể được liên kết tới nhiều container, trong số các liên kết đó có thể có liên kết chỉ-đọc và liên kết đọc-ghi, cùng một lúc.

Chia sẻ dữ liệu giữa nhiều Docker Machine

Khi xây dựng các ứng dụng cần khả năng chịu lỗi cao, bạn có thể cần phải cấu hình cho ứng dụng có nhiều nhân bản và cùng truy cập tới cùng một nguồn tài nguyên tập tin.

Có nhiều cách để đạt được mục tiêu. Đặt tài nguyên vào một cloud hoặc một nguồn lưu trữ ngoài (NFS hoặc Amazon S3 chẳng hạn).

Các Docker volume driver cho phép trừu tượng hóa các chi tiết triển khai ra khỏi mã logic của ứng dụng. Điều này rất có lợi trong các tình huống cần dịch chuyển nguồn tài nguyên từ dịch vụ này sang dịch vụ khác.

Sao lưu, phục hồi và chuyển di volume

Volume rất dễ sao lưu cũng như phục hồi hay chuyển di (migrate). Đơn giản chỉ cần liên kết volume và thư mục sao lưu vào một container có sẵn công cụ sao lưu hay phục hồi.

Cờ --volumes-from được dùng để khởi động một container và liên kết toàn bộ các volume đang liên kết với một container khác. Cơ chế này rất hữu dụng khi sao lưu và phục hồi volume.

Sao lưu

Lấy ví dụ, có một container có tên dbstore mà dữ liệu hoạt động của nó được đặt tại volume dbdata như sau:

$ docker run -v /dbdata --name dbstore ubuntu /bin/bash

Câu lệnh sau đây sẽ:

  • Khởi động một container mới và mount volume của dbstore.
  • Liên kết thư mục hiện hành từ máy host vào thư mục /backup trong container.
  • Thực thi một câu lệnh để tar nội dung của dbdata vào tập tin backup.tar nằm trong thư mục /backup.
$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

Khi câu lệnh tar thực thi xong, container sẽ dừng hoạt động, bị xóa; và chúng ta còn lại tập tin backup.tar, hay nói cách khác là bản sao lưu của dbdata, nằm trong thư mục hiện hành.

Phục hồi

Cách thức tương tự có thể được dùng để phục hồi bản sao lưu đã tạo.

$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"

Chúng ta có thể dùng cách này để phục hồi bản sao lưu vào một container khác với ban đầu, kết quả có được là một nhân bản của volume dbdata, nói cách khác là dbdata đã được chuyển di sang container mới.

Xóa bỏ volume

Docker volume không bị xóa theo khi xóa container. Do đó cần cân nhắc xóa volume khi không sử dụng dữ liệu trong đó nữa.

Xóa volume vô danh

Để các volume vô danh tự động được xóa, sử dụng cờ --rm. Khi container được tạo bởi câu lệnh dưới đây bị xóa, Docker Engine sẽ xóa bỏ volume /foo, nhưng volume awesome thì không.

$ docker run --rm -v /foo -v awesome:/bar busybox top

Xóa bỏ tất cả các volume

Sử dụng phép prune trên volume.

$ docker volume prune

Tài liệu tham khảo:

https://docs.docker.com/storage/volumes/

_

Leave a Comment

Your email address will not be published. Required fields are marked *