Cách xử lý lưu trữ liên tục (ví dụ: cơ sở dữ liệu) trong Docker


993

Làm thế nào để mọi người đối phó với việc lưu trữ liên tục cho các container Docker của bạn?

Tôi hiện đang sử dụng phương pháp này: xây dựng hình ảnh, ví dụ cho PostgreSQL, sau đó khởi động bộ chứa với

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

IMHO, có một nhược điểm, mà tôi không bao giờ (vô tình) xóa container "c0dbc34fd631".

Một ý tưởng khác là gắn khối lượng máy chủ "-v" vào vùng chứa, tuy nhiên, userid trong vùng chứa không nhất thiết phải khớp với userid từ máy chủ, và sau đó các quyền có thể bị rối tung.

Lưu ý: Thay vì --volumes-from 'cryptic_id'bạn cũng có thể sử dụng --volumes-from my-data-containermy-data-containerlà một cái tên bạn đã gán cho một container dữ liệu duy nhất, ví dụ docker run --name my-data-container ...(xem câu trả lời được chấp nhận)


Xin lỗi, tôi nói sai, tôi muốn nói: tất cả các trường hợp tương lai của tôi từ hình ảnh đó phụ thuộc vào container đó. Nếu tôi vô tình xóa container đó, tôi sẽ gặp rắc rối.
ép trái cây

@AntonStrogonoff - vâng, phân nhịp lỗi - tôi muốn nói: tôi cần phải chắc chắn rằng tôi sẽ không bao giờ xóa (có thể) chứa cũ, bởi vì sau đó các tài liệu tham khảo các "dai dẳng" lưu trữ cũng sẽ ra đi
juwalter

nó phải được --name. bạn có-name
Shammel Lee 9/11/2016

Câu trả lời:


986

Docker 1.9.0 trở lên

Sử dụng API khối lượng

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

Điều này có nghĩa là mẫu container chỉ chứa dữ liệu phải được bỏ qua theo hướng có lợi cho khối lượng mới.

Trên thực tế, API khối lượng chỉ là một cách tốt hơn để đạt được mô hình chứa dữ liệu.

Nếu bạn tạo một thùng chứa với -v volume_name:/container/fs/pathDocker sẽ tự động tạo một khối lượng được đặt tên cho bạn, có thể:

  1. Được liệt kê thông qua docker volume ls
  2. Được xác định thông qua docker volume inspect volume_name
  3. Được sao lưu như một thư mục bình thường
  4. Sao lưu như trước thông qua một --volumes-fromkết nối

API khối lượng mới thêm một lệnh hữu ích cho phép bạn xác định khối lượng lơ lửng:

docker volume ls -f dangling=true

Và sau đó loại bỏ nó thông qua tên của nó:

docker volume rm <volume name>

Khi @mpugach gạch chân trong các bình luận, bạn có thể thoát khỏi tất cả các khối lượng lơ lửng với một lớp lót đẹp:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune

Docker 1.8.x trở xuống

Cách tiếp cận có vẻ hoạt động tốt nhất cho sản xuất là sử dụng chỉ chứa dữ liệu .

Container chỉ chứa dữ liệu được chạy trên hình ảnh barebones và thực tế không làm gì ngoài việc để lộ một khối lượng dữ liệu.

Sau đó, bạn có thể chạy bất kỳ vùng chứa nào khác để có quyền truy cập vào khối lượng vùng chứa dữ liệu:

docker run --volumes-from data-container some-other-container command-to-execute
  • Ở đây bạn có thể có được một hình ảnh tốt về cách sắp xếp các container khác nhau.
  • Ở đây có một cái nhìn sâu sắc tốt về cách khối lượng làm việc.

Trong bài đăng trên blog này có một mô tả hay về cái gọi là container dưới dạng mẫu âm lượng , điều này làm rõ điểm chính của việc chỉ chứa các dữ liệu .

Tài liệu Docker hiện có mô tả DEFINITIVE của container dưới dạng khối lượng / s .

Sau đây là quy trình sao lưu / khôi phục cho Docker 1.8.x trở xuống.

SAO LƯU:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
  • --rm: loại bỏ container khi nó thoát
  • --volume-from DATA: đính kèm vào các khối được chia sẻ bởi bộ chứa DATA
  • -v $ (pwd): / backup: bind mount thư mục hiện tại vào container; để ghi tập tin tar vào
  • busybox: một hình ảnh nhỏ đơn giản hơn - tốt cho việc bảo trì nhanh chóng
  • tar cvf /backup/backup.tar / data: tạo tệp tar không nén của tất cả các tệp trong thư mục / data

NHÀ HÀNG:

# Create a new data container
$ sudo docker run -v /data -name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# Compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt

Dưới đây là một bài viết hay từ Brian Goff xuất sắc giải thích lý do tại sao sử dụng cùng một hình ảnh cho một container và một container dữ liệu là tốt.


8
Đó là một công cụ khác nhau cho một nhu cầu khác nhau. --volumes-fromcho phép bạn chia sẻ không gian đĩa --linkcho phép bạn chia sẻ dịch vụ.
tommasop

3
Có một dự án khác trong các tác phẩm dành riêng cho loại điều này, có thể thêm nó vào câu trả lời này như một tài liệu tham khảo để xem? github.com/ClusterHQ/flocker
Andre

9
Các thùng chứa dữ liệu không có ý nghĩa gì và thực sự là ý tưởng tồi! Container chỉ có nghĩa là một cái gì đó khi một tiến trình đang chạy trong đó, nếu không nó chỉ là một phần của hệ thống tệp máy chủ. Bạn chỉ có thể gắn một âm lượng với -v đó là tùy chọn duy nhất và tốt nhất. Bạn có quyền kiểm soát hệ thống tập tin và đĩa vật lý bạn sử dụng.
Boynux

11
Đúng, kể từ Docker 1.9, việc tạo các Tập tin được đặt tên bằng API khối ( docker volume create --name mydata) được ưu tiên hơn Bộ chứa khối lượng dữ liệu. Folks tại Docker mình gợi ý rằng dữ liệu Khối lượng Container “ không còn được coi là một mô hình khuyến cáo ”, “ tên khối lượng nên có thể thay thế khối lượng dữ liệu chỉ trong hầu hết (nếu không phải tất cả) trường hợp ,” và “ không có lý do tôi có thể thấy việc sử dụng container chỉ dữ liệu .
Quinn Comendant

8
@coding, tôi buồn bạn buồn, một phần vì bạn đang đánh giá câu trả lời với độ trễ 3 năm và một phần vì câu trả lời thực sự đúng trong tất cả lịch sử của nó. Nếu bạn có bất cứ lời khuyên nào, hãy bình luận để tôi có thể tích hợp câu trả lời và giúp mọi người không buồn
tommasop

75

Trong Docker phát hành v1.0 , liên kết một tập tin hoặc thư mục trên máy chủ có thể được thực hiện bằng lệnh đã cho:

$ docker run -v /host:/container ...

Âm lượng trên có thể được sử dụng làm bộ lưu trữ liên tục trên máy chủ đang chạy Docker.


3
Đây phải là câu trả lời được đề xuất vì nó ít phức tạp hơn nhiều so với phương pháp tiếp cận khối lượng có nhiều phiếu tại thời điểm này
insitusec

2
Tôi muốn có một cờ để chỉ định một ánh xạ host-uid: container-uid và host-gid: container-gid khi sử dụng lệnh mount âm lượng này.
hung hăng

35

Kể từ Docker Compose 1.6, giờ đây đã có hỗ trợ cải thiện về khối lượng dữ liệu trong Docker Compose. Tệp soạn thảo sau đây sẽ tạo ra một hình ảnh dữ liệu sẽ tồn tại giữa lúc khởi động lại (hoặc thậm chí loại bỏ) các thùng chứa cha mẹ:

Dưới đây là thông báo blog: Soạn 1.6: Tệp soạn thảo mới để xác định mạng và âm lượng

Đây là một ví dụ soạn tập tin:

version: "2"

services:
  db:
    restart: on-failure:10
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
  web:
    restart: on-failure:10
    build: .
    command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

volumes:
  db-data:

Theo như tôi có thể hiểu: Điều này sẽ tạo ra một thùng chứa khối lượng dữ liệu ( db_data) sẽ tồn tại giữa các lần khởi động lại.

Nếu bạn chạy: docker volume lsbạn sẽ thấy khối lượng của bạn được liệt kê:

local               mypthonapp_db-data
...

Bạn có thể biết thêm chi tiết về khối lượng dữ liệu:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

Một số thử nghiệm:

# Start the containers
docker-compose up -d

# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...

# Stop and remove the containers:
docker-compose stop
docker-compose rm -f

# Start it back up again
docker-compose up -d

# Verify the data is still there
...
(it is)

# Stop and remove with the -v (volumes) tag:

docker-compose stop
docker=compose rm -f -v

# Up again ..
docker-compose up -d

# Check the data is still there:
...
(it is).

Ghi chú:

  • Bạn cũng có thể chỉ định các trình điều khiển khác nhau trong volumeskhối. Ví dụ: Bạn có thể chỉ định trình điều khiển Flocker cho db_data:

    volumes:
      db-data:
        driver: flocker
    
  • Khi họ cải thiện sự tích hợp giữa Docker Swarm và Docker Compose (và có thể bắt đầu tích hợp Flocker vào hệ sinh thái Docker (tôi nghe tin đồn rằng Docker đã mua Flocker), tôi nghĩ cách tiếp cận này sẽ ngày càng mạnh mẽ.

Tuyên bố miễn trừ trách nhiệm: Cách tiếp cận này đầy hứa hẹn và tôi đang sử dụng thành công trong môi trường phát triển. Tôi sẽ thấy e ngại khi sử dụng nó trong sản xuất!


Flocker đã ngừng hoạt động và không có nhiều hoạt động trên repo github
Krishna

17

Trong trường hợp không rõ ràng từ bản cập nhật 5 của câu trả lời được chọn, kể từ Docker 1.9, bạn có thể tạo các khối có thể tồn tại mà không được liên kết với một bộ chứa cụ thể, do đó làm cho mẫu "chỉ chứa dữ liệu" bị lỗi thời.

Xem Container chỉ dữ liệu lỗi thời với docker 1.9.0? # 17798 .

Tôi nghĩ rằng các nhà bảo trì Docker nhận ra mẫu thùng chứa dữ liệu chỉ là một chút mùi thiết kế và quyết định tạo ra một khối thực thể riêng biệt có thể tồn tại mà không cần một thùng chứa liên quan.


13

Mặc dù đây vẫn là một phần của Docker cần một số công việc , bạn nên đặt âm lượng vào Dockerfile bằng lệnh VOLUME để bạn không cần sao chép các ổ đĩa từ một thùng chứa khác.

Điều đó sẽ làm cho các container của bạn ít phụ thuộc lẫn nhau hơn và bạn không phải lo lắng về việc xóa một container này ảnh hưởng đến một container khác.


Đối số mặt trái là các thùng chứa "chỉ dữ liệu" cuối cùng là tham chiếu cuối cùng cho khối lượng dữ liệu (Docker phá hủy khối lượng dữ liệu sau khi bộ chứa cuối cùng tham chiếu khối lượng đó được gỡ bỏ docker rm)
WineSoaken

2
Hướng dẫn chính thức này từ Docker gợi ý khác: docs.docker.com/userguide/dockervolume/ Lời "Khối lượng dữ liệu được thiết kế để duy trì dữ liệu, độc lập với vòng đời của người chứa. Do đó, Docker không bao giờ tự động xóa các khối khi bạn xóa vùng chứa, cũng không Rác rác thu thập các khối lượng không còn được tham chiếu bởi một container. "
Alex

12

Khi sử dụng Docker Compose , chỉ cần đính kèm một ổ đĩa được đặt tên, ví dụ:

version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - db_data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: root
volumes:
  db_data:

9

Câu trả lời của @ tommasop là tốt và giải thích một số cơ chế sử dụng các thùng chứa chỉ có dữ liệu. Nhưng như một người ban đầu nghĩ rằng các thùng chứa dữ liệu thật ngớ ngẩn khi người ta chỉ có thể gắn kết một khối lượng với máy chủ (như được đề xuất bởi một số câu trả lời khác), nhưng bây giờ nhận ra rằng trên thực tế, các thùng chứa chỉ có dữ liệu khá gọn gàng, tôi có thể đề xuất bài đăng trên blog về chủ đề này: Tại sao Docker Data Container (Tập!) là tốt

Xem thêm: câu trả lời của tôi cho câu hỏi "Cách tốt nhất (tốt nhất) để quản lý quyền đối với khối lượng chia sẻ Docker là gì? " Để biết ví dụ về cách sử dụng bộ chứa dữ liệu để tránh các vấn đề như quyền và ánh xạ uid / gid với máy chủ.

Để giải quyết một trong những mối quan tâm ban đầu của OP: không được xóa vùng chứa dữ liệu. Ngay cả khi vùng chứa dữ liệu bị xóa, dữ liệu sẽ không bị mất miễn là bất kỳ vùng chứa nào có tham chiếu đến ổ đĩa đó, tức là bất kỳ vùng chứa nào gắn âm lượng qua --volumes-from. Vì vậy, trừ khi tất cả các container liên quan bị dừng và xóa (người ta có thể coi đây là tương đương với một sự tình cờ rm -fr /), dữ liệu là an toàn. Bạn luôn có thể tạo lại bộ chứa dữ liệu bằng cách thực hiện --volumes-frombất kỳ bộ chứa nào có tham chiếu đến ổ đĩa đó.

Như mọi khi, tạo bản sao lưu mặc dù!

CẬP NHẬT: Docker hiện có khối lượng có thể được quản lý độc lập với các container, điều này càng làm cho việc này dễ quản lý hơn.


9

Có một số cấp độ quản lý dữ liệu liên tục, tùy thuộc vào nhu cầu của bạn:

  • Lưu trữ nó trên máy chủ của bạn
    • Sử dụng cờ -v host-path:container-pathđể duy trì dữ liệu thư mục container vào thư mục máy chủ.
    • Sao lưu / khôi phục xảy ra bằng cách chạy một thùng chứa sao lưu / khôi phục (như tutumcloud / dockup) được gắn vào cùng một thư mục.
  • Tạo một thùng chứa dữ liệu và gắn kết khối lượng của nó vào thùng chứa ứng dụng của bạn
    • Tạo một thùng chứa xuất dữ liệu, sử dụng --volumes-fromđể gắn dữ liệu đó vào thùng chứa ứng dụng của bạn.
    • Sao lưu / khôi phục giống như các giải pháp trên.
  • Sử dụng plugin khối lượng Docker sao lưu dịch vụ bên ngoài / bên thứ ba
    • Các plugin khối lượng Docker cho phép nguồn dữ liệu của bạn đến từ bất cứ đâu - NFS, AWS (S3, EFS và EBS)
    • Tùy thuộc vào plugin / dịch vụ, bạn có thể đính kèm một hoặc nhiều container vào một ổ đĩa.
    • Tùy thuộc vào dịch vụ, sao lưu / khôi phục có thể được tự động cho bạn.
    • Mặc dù điều này có thể rườm rà khi thực hiện thủ công, một số giải pháp phối hợp - chẳng hạn như Rancher - có thể sử dụng đơn giản và dễ sử dụng.
    • Đoàn xe là giải pháp dễ nhất để làm điều này bằng tay.

8

Nếu bạn muốn di chuyển âm lượng của mình xung quanh, bạn cũng nên xem Flocker .

Từ README:

Flocker là một trình quản lý khối lượng dữ liệu và công cụ quản lý cụm Docker đa máy chủ. Với nó, bạn có thể kiểm soát dữ liệu của mình bằng chính các công cụ bạn sử dụng cho các ứng dụng phi trạng thái của mình bằng cách khai thác sức mạnh của ZFS trên Linux.

Điều này có nghĩa là bạn có thể chạy cơ sở dữ liệu, hàng đợi và lưu trữ khóa-giá trị trong Docker và di chuyển chúng xung quanh dễ dàng như phần còn lại của ứng dụng.


1
Cảm ơn Johann. Tôi làm việc tại ClusterHQ và tôi chỉ muốn lưu ý rằng chúng tôi đã vượt ra ngoài việc chỉ lưu trữ dựa trên ZFS. Bây giờ bạn có thể sử dụng Flocker với bộ lưu trữ như Amazon EBS hoặc Google Persistent Disk. Dưới đây là danh sách đầy đủ các tùy chọn lưu trữ: docs.clusterhq.com/en/latest/supported/ mẹo
ferrantim

1
Flocker đã ngừng và không nên được sử dụng portworx.com/ Hãy
jesugmz

5

Nó phụ thuộc vào kịch bản của bạn (điều này không thực sự phù hợp với môi trường sản xuất), nhưng đây là một cách:

Tạo một Docker MySQL MySQL

Ý chính của nó là sử dụng một thư mục trên máy chủ của bạn để duy trì dữ liệu.


6
Tuy nhiên, cảm ơn Ben - một trong những vấn đề tôi có thể thấy với cách tiếp cận này: tài nguyên hệ thống tệp (thư mục, tệp) sẽ được sở hữu bởi một uid từ trong bộ chứa docker / lxc (khách) - một vấn đề có thể va chạm với uid trên máy chủ ...
juwalter

1
Tôi nghĩ rằng bạn khá an toàn vì nó được điều hành bởi root, nhưng tôi đồng ý rằng đó là một bản hack - phù hợp với thử nghiệm tích hợp dev / ephemeral cục bộ. Đây chắc chắn là một lĩnh vực tôi muốn thấy nhiều mô hình / suy nghĩ xuất hiện. Bạn nên kiểm tra / đăng câu hỏi này lên nhóm google docker-dev
ben schwartz

Ben, cảm ơn vì giải pháp này! Tôi sẽ không gọi nó là hack mặc dù, nó có vẻ đáng tin cậy hơn nhiều so với container là khối lượng . Bạn có thấy bất kỳ nhược điểm nào trong trường hợp khi dữ liệu chỉ được sử dụng từ container không? (UID không thành vấn đề trong trường hợp này)
johndodo



0

Giải pháp của tôi là sử dụng cái mới docker cp, hiện có thể sao chép dữ liệu từ các container, không quan trọng là nó có chạy hay không và chia sẻ một khối lượng máy chủ đến cùng một vị trí nơi ứng dụng cơ sở dữ liệu đang tạo các tệp cơ sở dữ liệu của nó trong container . Giải pháp kép này hoạt động mà không có bộ chứa chỉ dữ liệu, trực tiếp từ bộ chứa cơ sở dữ liệu ban đầu.

Vì vậy, tập lệnh init systemd của tôi đang thực hiện công việc sao lưu cơ sở dữ liệu vào một kho lưu trữ trên máy chủ. Tôi đã đặt dấu thời gian trong tên tệp để không bao giờ viết lại tệp.

Nó đang làm điều đó trên ExecStartPre:

ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'

Và nó cũng đang làm điều tương tự trên ExecStopPost:

ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'

Thêm vào đó, tôi đã hiển thị một thư mục từ máy chủ lưu trữ dưới dạng chính xác đến cùng một vị trí nơi cơ sở dữ liệu được lưu trữ:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

Nó hoạt động rất tốt trên máy ảo của tôi (Tôi tự xây dựng một ngăn xếp LEMP): https://github.com/DJviolin/LEMP

Nhưng tôi chỉ không biết liệu đó có phải là một giải pháp "chống đạn" hay không khi cuộc sống của bạn phụ thuộc vào nó thực sự (ví dụ: webshop với các giao dịch trong bất kỳ milisecond nào có thể)?

Trong 20 phút 20 giây từ video ghi chú Docker chính thức này, người trình bày thực hiện điều tương tự với cơ sở dữ liệu:

Bắt đầu với Docker

"Đối với cơ sở dữ liệu, chúng tôi có một khối lượng, vì vậy chúng tôi có thể đảm bảo rằng, khi cơ sở dữ liệu tăng và giảm, chúng tôi không mất dữ liệu, khi bộ chứa cơ sở dữ liệu dừng lại."


Ý bạn là gì khi "... sử dụng ..." ? Và "... giao dịch trong bất kỳ milisecond nào có thể" ?
Peter Mortensen

0

Sử dụng Yêu cầu khối lượng liên tục (PVC) từ Kubernetes, đây là công cụ lập lịch và quản lý vùng chứa Docker:

Khối lượng liên tục

Ưu điểm của việc sử dụng Kubernetes cho mục đích này là:

  • Bạn có thể sử dụng bất kỳ bộ lưu trữ nào như NFS hoặc bộ lưu trữ khác và ngay cả khi nút bị hỏng, bộ lưu trữ không cần thiết.
  • Ngoài ra, dữ liệu trong các khối lượng như vậy có thể được cấu hình để được giữ lại ngay cả sau khi chính container bị phá hủy - để nó có thể được thu hồi, nếu cần, bởi một container khác.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.