Thứ năm, 21/05/2020 | 00:00 GMT+7

Cách chia sẻ dữ liệu giữa các container Docker

Docker là một công cụ chứa phổ biến được sử dụng để cung cấp cho các ứng dụng phần mềm một hệ thống file chứa mọi thứ chúng cần để chạy. Sử dụng containers Docker đảm bảo phần mềm sẽ hoạt động theo cùng một cách dù nó được triển khai ở đâu vì môi trường thời gian chạy của nó là nhất quán.

Nói chung, containers Docker là tạm thời, chỉ chạy miễn là lệnh được đưa ra trong containers hoàn tất. Tuy nhiên, đôi khi các ứng dụng cần chia sẻ quyền truy cập vào dữ liệu hoặc duy trì dữ liệu sau khi containers bị xóa. Database , nội dung do user tạo cho một trang web và file log chỉ là một vài ví dụ về dữ liệu không thực tế hoặc không thể đưa vào Docker image nhưng ứng dụng nào cần truy cập. Quyền truy cập liên tục vào dữ liệu được cung cấp với Docker Volumes .

Docker Volumes có thể được tạo và đính kèm trong cùng một lệnh tạo containers hoặc chúng có thể được tạo độc lập với bất kỳ containers nào và được đính kèm sau đó. Trong bài viết này, ta sẽ xem xét bốn cách khác nhau để chia sẻ dữ liệu giữa các containers .

Yêu cầu

Để theo dõi bài viết này, bạn cần một server Ubuntu 20.04 với những thứ sau:

Lưu ý: Mặc dù các yêu cầu đưa ra hướng dẫn để cài đặt Docker trên Ubuntu 20.04, các docker lệnh cho data volumes Docker trong bài viết này sẽ làm việc trên các hệ điều hành khác miễn là Docker đã được cài đặt và người sử dụng sudo đã được thêm vào docker group .

Bước 1 - Tạo một tập đĩa độc lập

Được giới thiệu trong bản phát hành 1.9 của Docker, lệnh docker volume create cho phép bạn tạo một ổ đĩa mà không liên quan đến bất kỳ containers cụ thể nào. Ta sẽ sử dụng lệnh này để thêm một ổ đĩa có tên là DataVolume1 :

  • docker volume create --name DataVolume1

Tên được hiển thị, cho biết rằng lệnh đã thành công:

Output
DataVolume1

Để sử dụng ổ đĩa, ta sẽ tạo một containers mới từ ảnh Ubuntu, sử dụng cờ --rm để tự động xóa nó khi ta thoát. Ta cũng sẽ sử dụng -v để gắn ổ đĩa mới. -v yêu cầu tên của tập, dấu hai chấm, sau đó là đường dẫn tuyệt đối đến nơi mà tập sẽ xuất hiện bên trong containers . Nếu các folder trong đường dẫn không tồn tại như một phần của hình ảnh, chúng sẽ được tạo khi lệnh chạy. Nếu họ thực sự tồn tại, sự mount dung lượng sẽ ẩn nội dung hiện có:

  • docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

Khi ở trong containers , hãy ghi một số dữ liệu vào ổ đĩa:

  • echo "Example1" > /datavolume1/Example1.txt

Bởi vì ta đã sử dụng cờ --rm , containers của ta sẽ tự động bị xóa khi ta thoát. Dung lượng của ta , tuy nhiên, vẫn sẽ có thể truy cập được.

  • exit

Ta có thể xác minh dung lượng có trên hệ thống của ta bằng cách docker volume inspect :

  • docker volume inspect DataVolume1
Output
[ { "CreatedAt": "2018-07-11T16:57:54Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data", "Name": "DataVolume1", "Options": {}, "Scope": "local" } ]

Lưu ý: Ta thậm chí có thể xem dữ liệu trên server lưu trữ tại đường dẫn được liệt kê là Mountpoint . Tuy nhiên, ta nên tránh thay đổi nó, vì nó có thể gây hỏng dữ liệu nếu các ứng dụng hoặc containers không biết về các thay đổi.

Tiếp theo, hãy bắt đầu một containers mới và đính kèm DataVolume1 :

  • docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu

Xác minh nội dung:

  • cat /datavolume1/Example1.txt
Output
Example1

Thoát khỏi containers :

  • exit

Trong ví dụ này, ta đã tạo một tập, gắn nó vào một containers và xác minh tính tồn tại của nó.

Bước 2 - Tạo một ổ đĩa tồn tại khi containers bị xóa

Trong ví dụ tiếp theo của ta , ta sẽ tạo một ổ đĩa cùng lúc với containers , xóa containers , sau đó đính kèm ổ đĩa vào một containers mới.

Ta sẽ sử dụng lệnh docker run để tạo một containers mới bằng cách sử dụng hình ảnh Ubuntu cơ sở. -t sẽ cung cấp cho ta một terminal và -i sẽ cho phép ta tương tác với nó. Để rõ ràng, ta sẽ sử dụng --name để xác định containers .

Cờ -v sẽ cho phép ta tạo một tập mới, mà ta sẽ gọi là DataVolume2 . Ta sẽ sử dụng dấu hai chấm để phân tách tên này khỏi đường dẫn nơi ổ đĩa sẽ được gắn trong containers . Cuối cùng, ta sẽ chỉ định hình ảnh Ubuntu cơ sở và dựa vào lệnh mặc định trong tệp Docker của hình ảnh cơ sở Ubuntu , bash , để đưa ta vào một shell :

  • docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

Lưu ý: Cờ -v rất linh hoạt. Nó có thể liên kết số lượng hoặc đặt tên cho một tập chỉ với một chút điều chỉnh trong cú pháp. Nếu đối số đầu tiên bắt đầu bằng / hoặc ~/ bạn đang tạo số lượng liên kết. Loại bỏ điều đó và bạn đang đặt tên cho tập. Ví dụ:

  • -v /path:/path/in/container mount folder server , /path tại /path/in/container
  • -v path:/path/in/container tạo ra một ổ đĩa có tên là path không có mối quan hệ với server .

Để biết thêm về ràng buộc một folder từ server , hãy xem Cách chia sẻ dữ liệu giữa Docker Container và Server

Khi ở trong containers , ta sẽ ghi một số dữ liệu vào ổ đĩa:

  • echo "Example2" > /datavolume2/Example2.txt
  • cat /datavolume2/Example2.txt
Output
Example2

Hãy thoát khỏi containers :

  • exit

Khi ta khởi động lại containers , ổ đĩa sẽ tự động mount :

  • docker start -ai Container2

Hãy xác minh ổ đĩa đã thực sự được mount và dữ liệu của ta vẫn còn nguyên:

  • cat /datavolume2/Example2.txt
Output
Example2

Cuối cùng, hãy thoát và dọn dẹp:

  • exit

Docker sẽ không cho phép ta xóa một tập nếu nó được tham chiếu bởi một containers . Hãy xem điều gì sẽ xảy ra khi ta thử:

  • docker volume rm DataVolume2

Thông báo cho ta biết rằng ổ đĩa vẫn đang được sử dụng và cung cấp version dài của ID containers :

Output
Error response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]

Ta có thể sử dụng ID này để xóa containers :

  • docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
Output
d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

Xóa containers sẽ không ảnh hưởng đến âm lượng. Ta có thể thấy nó vẫn hiện diện trên hệ thống bằng cách liệt kê các ổ đĩa có ổ đĩa docker volume ls :

  • docker volume ls
Output
DRIVER VOLUME NAME local DataVolume2

Và ta có thể sử dụng docker volume rm để loại bỏ nó:

  • docker volume rm DataVolume2

Trong ví dụ này, ta đã tạo một data volumes trống đồng thời với việc ta tạo một containers . Trong ví dụ tiếp theo, ta sẽ khám phá điều gì sẽ xảy ra khi ta tạo một ổ đĩa với một folder containers đã chứa dữ liệu.

Bước 3 - Tạo một tập từ một folder hiện có với dữ liệu

Nói chung, việc tạo một volume độc lập với docker volume create và tạo một docker volume create trong khi tạo containers là tương đương nhau, với một ngoại lệ. Nếu ta tạo một ổ đĩa đồng thời với việc ta tạo một containers ta cung cấp đường dẫn đến một folder chứa dữ liệu trong hình ảnh cơ sở, thì dữ liệu đó sẽ được sao chép vào ổ đĩa.

Ví dụ: ta sẽ tạo một containers và thêm data volumes tại /var , một folder chứa dữ liệu trong hình ảnh cơ sở:

  • docker run -ti --rm -v DataVolume3:/var ubuntu

Tất cả nội dung từ folder /var của ảnh cơ sở được sao chép vào ổ đĩa và ta có thể gắn ổ đĩa đó vào một containers mới.

Thoát khỏi containers hiện tại:

  • exit

Lần này, thay vì dựa vào lệnh bash mặc định của hình ảnh cơ sở, ta sẽ đưa ra ls của riêng mình, lệnh này sẽ hiển thị nội dung của ổ đĩa mà không cần nhập shell :

  • docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3

Thư mục datavolume3 bây giờ có một bản sao nội dung của folder /var của ảnh cơ sở:

Output
backups cache lib local lock log mail opt run spool tmp

Không chắc rằng ta muốn mount /var/ theo cách này, nhưng điều này có thể hữu ích nếu ta đã tạo hình ảnh của riêng mình và muốn một cách dễ dàng để bảo quản dữ liệu. Trong ví dụ tiếp theo của ta , ta sẽ chứng minh cách một dung lượng có thể được chia sẻ giữa nhiều containers .

Bước 4 - Chia sẻ dữ liệu giữa nhiều containers Docker

Lúc này, ta đã đính kèm một tập vào một container tại một thời điểm. Thông thường, ta sẽ muốn nhiều containers gắn vào cùng một data volumes . Điều này tương đối dễ thực hiện, nhưng có một cảnh báo quan trọng: tại thời điểm này, Docker không xử lý việc khóa file . Nếu bạn cần nhiều containers ghi vào ổ đĩa, thì các ứng dụng chạy trong các containers đó phải được thiết kế để ghi vào các repository dữ liệu được chia sẻ nhằm ngăn ngừa hỏng dữ liệu.

Tạo Container4 và DataVolume4

Sử dụng docker run để tạo một containers mới có tên Container4 với một data volumes được đính kèm:

  • docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

Tiếp theo, ta sẽ tạo một file và thêm một số văn bản:

  • echo "This file is shared between containers" > /datavolume4/Example4.txt

Sau đó, ta sẽ thoát khỏi containers :

  • exit

Điều này đưa ta trở lại dấu nhắc lệnh của server , nơi ta sẽ tạo một containers mới để mount data volumes từ Container4 .

Tạo Container5 và Gắn các dung lượng từ Container4

Ta sẽ tạo Container5 và mount các ổ từ Container4 :

  • docker run -ti --name=Container5 --volumes-from Container4 ubuntu

Hãy kiểm tra độ bền của dữ liệu:

  • cat /datavolume4/Example4.txt
Output
This file is shared between containers

Bây giờ, hãy nối một số văn bản từ Container5 :

  • echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

Cuối cùng, ta sẽ thoát khỏi containers :

  • exit

Tiếp theo, ta sẽ kiểm tra xem dữ liệu của ta vẫn còn trong Container4 .

Xem các thay đổi được thực hiện trong container5

Hãy kiểm tra những thay đổi đã được Container5 ghi vào data volumes bằng cách khởi động lại Container4 :

  • docker start -ai Container4

Kiểm tra các thay đổi:

  • cat /datavolume4/Example4.txt
Output
This file is shared between containers Both containers can write to DataVolume4

Bây giờ ta đã xác minh cả hai containers đều có thể đọc và ghi từ khối dữ liệu, ta sẽ thoát khỏi containers :

  • exit

, Docker không xử lý bất kỳ khóa file nào, vì vậy các ứng dụng phải tính đến việc file tự khóa. Có thể gắn dung lượng Docker ở dạng chỉ đọc đảm bảo rằng dữ liệu sẽ không xảy ra tình cờ khi containers yêu cầu quyền truy cập chỉ đọc bằng cách thêm :ro . Hãy xem cách này hoạt động như thế nào.

Khởi động Vùng chứa 6 và Gắn Ổ đĩa Chỉ đọc

Khi một ổ đĩa đã được mount trong một containers , thay vì ngắt kết nối nó như ta làm với hệ thống file Linux điển hình, thay vào đó ta có thể tạo một containers mới được mount theo cách ta muốn và nếu cần, hãy xóa containers trước đó. Để đặt ổ đĩa ở chế độ chỉ đọc, ta thêm :ro vào cuối tên containers :

  • docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

Ta sẽ kiểm tra trạng thái chỉ đọc bằng cách cố gắng xóa file mẫu của ta :

  • rm /datavolume4/Example4.txt
Output
rm: cannot remove '/datavolume4/Example4.txt': Read-only file system

Cuối cùng, ta sẽ thoát khỏi containers và dọn dẹp các containers và dung lượng thử nghiệm của ta :

  • exit

Bây giờ ta đã hoàn tất, hãy dọn dẹp các containers và dung lượng của ta :

  • docker rm Container4 Container5 Container6
  • docker volume rm DataVolume4

Trong ví dụ này, ta đã chỉ ra cách chia sẻ dữ liệu giữa hai containers bằng cách sử dụng một ổ đĩa dữ liệu và cách gắn một ổ đĩa dữ liệu dưới dạng chỉ đọc.

Kết luận

Trong hướng dẫn này, ta đã tạo một data volumes cho phép dữ liệu tồn tại thông qua việc xóa containers . Ta đã chia sẻ data volumes giữa các containers , với lưu ý các ứng dụng cần được thiết kế để xử lý việc khóa file nhằm ngăn chặn dữ liệu bị hỏng. Cuối cùng, ta đã hướng dẫn cách gắn một tập chia sẻ ở chế độ chỉ đọc. Nếu bạn muốn tìm hiểu về cách chia sẻ dữ liệu giữa các containers và hệ thống lưu trữ, hãy xem Cách chia sẻ dữ liệu giữa Vùng chứa Docker và Server .


Tags:

Các tin liên quan

Cách sử dụng Traefik 1.7.21 làm Reverse Proxy cho Docker Containers trên CentOS 7
2020-05-12
Cách cài đặt Drupal với Docker Compose
2020-04-25
Cách xây dựng và triển khai ứng dụng Flask bằng Docker trên Ubuntu 18.04
2020-04-05
Como Conteinerizar um aplicativo Laravel para desenvolvimento com o Docker Compose em Ubuntu 18.04
2020-02-20
Cách tạo ứng dụng Node.js với Docker [Quickstart]
2020-02-06
Cách cài đặt Docker Compose trên Debian 10
2020-01-30
Cách chứa một ứng dụng Laravel để phát triển với Docker Compose trên Ubuntu 18.04
2020-01-23
Cách chứa một ứng dụng Laravel để phát triển với Docker Compose trên Ubuntu 18.04
2020-01-23
Lưu trữ một ứng dụng Ruby on Rails để phát triển với Docker Compose
2019-12-27
Làm việc với nhiều container bằng Docker Compose
2019-12-20