Làm thế nào để duy trì dữ liệu trong cơ sở dữ liệu postgres được neo bằng cách sử dụng khối lượng


205

Docker tập tin soạn thảo của tôi có ba container, web, nginx và postgres. Postgres trông như thế này:

postgres:
  container_name: postgres
  restart: always
  image: postgres:latest
  volumes:
    - ./database:/var/lib/postgresql
  ports:
    - "5432:5432

Mục tiêu của tôi là gắn kết một khối lượng tương ứng với một thư mục cục bộ được gọi ./databasebên trong thùng chứa postgres như /var/lib/postgres. Khi tôi khởi động các thùng chứa này và chèn dữ liệu vào postgres, tôi xác minh rằng /var/lib/postgres/data/base/nó chứa đầy dữ liệu tôi đang thêm (trong thùng chứa postgres), nhưng trong hệ thống cục bộ của tôi, ./databasechỉ nhận được một datathư mục trong đó, tức ./database/datalà được tạo, nhưng nó trống . Tại sao?

Ghi chú:

CẬP NHẬT 1

Theo đề nghị của Nick, tôi đã làm một docker inspectvà tìm thấy:

    "Mounts": [
        {
            "Source": "/Users/alex/Documents/MyApp/database",
            "Destination": "/var/lib/postgresql",
            "Mode": "rw",
            "RW": true,
            "Propagation": "rprivate"
        },
        {
            "Name": "e5bf22471215db058127109053e72e0a423d97b05a2afb4824b411322efd2c35",
            "Source": "/var/lib/docker/volumes/e5bf22471215db058127109053e72e0a423d97b05a2afb4824b411322efd2c35/_data",
            "Destination": "/var/lib/postgresql/data",
            "Driver": "local",
            "Mode": "",
            "RW": true,
            "Propagation": ""
        }
    ],

Điều này làm cho có vẻ như dữ liệu đang bị đánh cắp bởi một tập khác mà tôi không tự viết mã. Không chắc sao lại thế. Là hình ảnh postgres tạo ra khối lượng đó cho tôi? Nếu vậy, có cách nào để sử dụng âm lượng đó thay vì âm lượng tôi đang lắp khi khởi động lại không? Mặt khác, có cách nào tốt để vô hiệu hóa âm lượng khác đó và sử dụng âm lượng của riêng tôi ./databasekhông?

CẬP NHẬT 2

Tôi tìm thấy giải pháp, nhờ Nick! (và một người bạn khác) Trả lời dưới đây.


Bạn đã chạy initdbdòng lệnh để khởi tạo cụm cơ sở dữ liệu của mình chưa?
Sebastian Webber

Bạn có chắc thư mục con dữ liệu của bạn thực sự trống? Nó có thể có quyền truy cập đặc biệt.
Yaroslav Stavnichiy

Cảm ơn vì đã trở lại với tôi rất nhanh! Tôi đang sử dụng một ứng dụng bình, vì vậy tôi from app import dbdb.create_all()từ docker runsau khi bắt đầu các thùng chứa. Tôi không initdbtrực tiếp từ dòng lệnh.
Alex Lenail

1
@YaroslavStavnichiy Tôi không biết làm thế nào khác để kiểm tra điều đó hơn sudo su -và nhìn vào ./database/data. Không có gì trong đó xa như tôi có thể nói.
Alex Lenail

Ai đó có thể thấy điều này hữu ích: mẫu soạn thảo tệp vẫn tồn tại các postgres, dữ liệu tìm kiếm và phương tiện truyền thông, stackoverflow.com/a/56475980/5180118
ArdentLearner

Câu trả lời:


253

Thật kỳ lạ, giải pháp cuối cùng đã thay đổi

volumes:
  - ./postgres-data:/var/lib/postgresql

đến

volumes:
  - ./postgres-data:/var/lib/postgresql/data

45
Chỉ cần một "lý do" nhanh chóng cho câu trả lời này (hoạt động). Theo các postgres folks, thư mục dữ liệu mặc định là /var/lib/postgresql/data- bạn có thể đọc ghi chú biến PGDATA tại đây: store.docker.com/images/ chủ
Matt Pavelle

2
Trong câu hỏi trên, OP nói rằng nó hoạt động cho anh ta mà không có / dữ liệu ở cuối. Đúng không?
Sid

2
Và thêm thư mục cục bộ vào .dockerignoretệp của bạn , đặc biệt là nếu bạn từng chuyển nó thành hình ảnh sản xuất. Xem codefresh.io/blog/not-ignore-dockerignore để thảo luận.
DSz

4
điều này vẫn không hoạt động đối với tôi (mac os x high sierra)
olidem

1
@ OlliD-Metz Tôi phải làm một việc docker rm my_postgres_container_1trước khi nó hoạt động (cũng là High Sierra).
giàu có

100

Bạn có thể tạo một khối lượng chung cho tất cả dữ liệu của Postgres

 docker volume create pgdata

hoặc bạn có thể đặt nó vào tập tin soạn thảo

   version: "3"
   services:
     db:
       image: postgres
       environment:
         - POSTGRES_USER=postgres
         - POSTGRES_PASSWORD=postgress
         - POSTGRES_DB=postgres
       ports:
         - "5433:5432"
       volumes:
         - pgdata:/var/lib/postgresql/data
       networks:
         - suruse
   volumes: 
     pgdata:

Nó sẽ tạo tên khối lượng pgdata và gắn khối lượng này vào đường dẫn của bộ chứa.

Bạn có thể kiểm tra khối lượng này

docker volume inspect pgdata

// output will be
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
        "Name": "pgdata",
        "Options": {},
        "Scope": "local"
    }
]

8
Nhận xét hơi muộn, nhưng sẽ không có dữ liệu rõ ràng này nếu tôi làm a docker-compose down -v. Và giải pháp cho điều đó là gì?
Sid

3
@Sid, vâng, nó sẽ! Chỉ cần cẩn thận với tùy chọn này.
olidem

1
Vì vậy, với docker-compose [down], âm lượng không còn tồn tại? Có dọn dẹp đầy đủ ngay cả của khối lượng?
Paul

2
@Sid Bình luận thậm chí sau đó, nhưng bạn có thể sử dụng docker-compose down --rmi all mà không cần sự -vlựa chọn và nó sẽ xóa bỏ "tất cả mọi thứ" ngoại trừ khối lượng, tức là container, mạng, hình ảnh, vv Tôi làm điều đó khi triển khai đồng thời cho phép dữ liệu bền bỉ.
code_dredd

13

Tôi sẽ tránh sử dụng một con đường tương đối. Hãy nhớ rằng docker là mối quan hệ daemon / client.

Khi bạn đang thực thi việc soạn thảo, về cơ bản, nó chỉ phân tích thành các lệnh máy khách docker khác nhau, sau đó được chuyển đến trình nền. Điều ./databaseđó sau đó liên quan đến daemon , không phải máy khách.

Bây giờ, nhóm phát triển docker có một số trở lại về vấn đề này , nhưng điểm mấu chốt là nó có thể có một số kết quả bất ngờ.

Nói tóm lại, đừng sử dụng một đường dẫn tương đối, hãy sử dụng một đường dẫn tuyệt đối.


Cảm ơn câu trả lời này! Đáng buồn thay, tôi không nghĩ rằng nó đã làm việc. Tôi đã thay đổi dòng thành một đường dẫn tuyệt đối và sau khi chèn dữ liệu, database/datathư mục vẫn trống = (
Alex Lenail

K. Tiếp theo là chạy docker inspecttrên container và đảm bảo rằng container nhận biết được âm lượng (chỉ trong trường hợp soạn thảo bị nhầm lẫn hoặc một cái gì đó). (lưu ý: kiểm tra docker có thể có dữ liệu nhạy cảm, vì vậy đừng dán nó vào đây mà không cần munging ;-) Sau đó, vấn đề kiểm tra quyền (mặc dù điều đó thường sẽ xuất hiện lỗi)
Nick Burke

Aha! @Nick Burke Tôi nghĩ bạn đã tìm thấy thứ gì đó. Tôi đã cập nhật câu hỏi.
Alex Lenail

2

Tôi nghĩ rằng bạn chỉ cần tạo âm lượng của bạn bên ngoài docker trước với một docker create -v /location --namevà sau đó sử dụng lại nó.

Và tại thời điểm tôi thường sử dụng docker rất nhiều, không thể sử dụng âm lượng docker tĩnh với định nghĩa dockerfile vì vậy đề nghị của tôi là thử dòng lệnh (cuối cùng là với tập lệnh).

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.