วิธีเก็บข้อมูลในฐานข้อมูล postgres ที่ปรับเทียบแล้วโดยใช้วอลุ่ม


205

ไฟล์เขียนของนักเทียบท่าของฉันมีสามคอนเทนเนอร์เว็บ nginx และ postgres Postgres มีลักษณะเช่นนี้:

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

เป้าหมายของฉันคือการติดปริมาณซึ่งสอดคล้องกับโฟลเดอร์ท้องถิ่นเรียกว่า./databaseภายใน postgres /var/lib/postgresคอนเทนเนอร์ เมื่อฉันเริ่มต้นคอนเทนเนอร์เหล่านี้และแทรกข้อมูลลงใน postgres ฉันตรวจสอบว่า/var/lib/postgres/data/base/เต็มไปด้วยข้อมูลที่ฉันเพิ่ม (ในคอนเทนเนอร์ postgres) แต่ในระบบท้องถิ่นของฉัน./databaseจะได้รับdataโฟลเดอร์เท่านั้นเช่น./database/dataถูกสร้างขึ้น แต่ว่างเปล่า . ทำไม?

หมายเหตุ:

อัพเดท 1

ตามคำแนะนำของ Nick ฉันได้docker inspectและพบ:

    "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": ""
        }
    ],

ซึ่งทำให้ดูเหมือนว่าข้อมูลกำลังถูกขโมยโดยโวลุ่มอื่นที่ฉันไม่ได้รหัสด้วยตัวเอง ไม่แน่ใจว่าทำไม ภาพ postgres สร้างระดับเสียงนั้นสำหรับฉันหรือไม่ ถ้าเป็นเช่นนั้นจะมีวิธีการใช้ระดับเสียงนั้นแทนที่จะเป็นปริมาณที่ฉันกำลังติดตั้งเมื่อฉันรีสตาร์ท? มิฉะนั้นจะมีวิธีที่ดีในการปิดการใช้งานไดรฟ์ข้อมูลอื่นและใช้งานเอง./databaseหรือไม่?

อัพเดท 2

ฉันพบวิธีแก้ปัญหาขอบคุณ Nick! (และเพื่อนอีกคน) คำตอบด้านล่าง


คุณรันinitdbบรรทัดคำสั่งแล้วเพื่อเริ่มต้นคลัสเตอร์ฐานข้อมูลของคุณหรือไม่
เซบาสเตียนเว็บเบอร์

คุณแน่ใจหรือไม่ว่าไดเรกทอรีย่อยข้อมูลว่างเปล่าจริง ๆ มันอาจมีสิทธิ์การเข้าถึงพิเศษ
Yaroslav Stavnichiy

ขอบคุณที่กลับมาหาฉันอย่างรวดเร็ว! ฉันใช้แอปพลิเคขวดดังนั้นฉันfrom app import dbและdb.create_all()จากdocker runหลังจากที่เริ่มต้นภาชนะบรรจุ ฉันไม่ได้initdbโดยตรงจากบรรทัดคำสั่ง
Alex Lenail

1
@YaroslavStavnichiy ฉันไม่รู้วิธีอื่นที่จะตรวจสอบว่ากว่าsudo su -และมอง./database/dataมา ไม่มีอะไรในนั้นเท่าที่ฉันสามารถบอกได้
Alex Lenail

บางคนอาจพบว่ามีประโยชน์นี้: ตัวอย่างไฟล์เขียนที่ยังคงมีอยู่, การค้นหาที่ยืดหยุ่นและข้อมูลสื่อ, stackoverflow.com/a/56475980/5180118
ArdentLearner

คำตอบ:


253

น่าประหลาดใจที่วิธีแก้ปัญหาก็คือการเปลี่ยนแปลง

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

ถึง

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

45
เพียงแค่ "รวดเร็ว" สำหรับคำตอบนี้ (ใช้ได้ผล) สำหรับกลุ่ม postgres ไดเรกทอรีข้อมูลเริ่มต้นคือ/var/lib/postgresql/data- คุณสามารถอ่านบันทึกตัวแปร PGDATA ได้ที่นี่: store.docker.com/images/…
Matt Pavelle

2
ในคำถามข้างต้น OP บอกว่ามันใช้ได้กับเขาโดยที่ไม่มีข้อมูล / ในตอนท้าย ถูกต้องไหม
Sid

2
และเพิ่มไดเรกทอรีท้องถิ่นลงใน.dockerignoreไฟล์ของคุณโดยเฉพาะอย่างยิ่งถ้าคุณจะตัดทอนสิ่งนี้ลงในอิมเมจที่ใช้งานจริง ดูcodefresh.io/blog/not-ignore-dockerignoreสำหรับการสนทนา
dsz

4
ยังไม่สามารถใช้งานได้สำหรับฉัน (mac os x high sierra)
olidem

1
@ OlliD-Metz ฉันต้องทำdocker rm my_postgres_container_1ก่อนที่มันจะทำงาน (เช่น High Sierra)
รวย

100

คุณสามารถสร้างโวลุ่มทั่วไปสำหรับข้อมูล Postgres ทั้งหมด

 docker volume create pgdata

หรือคุณสามารถตั้งค่าเป็นไฟล์เขียน

   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:

มันจะสร้างชื่อปริมาณpgdataและเมานต์ไดรฟ์นี้เพื่อเส้นทางของภาชนะ

คุณสามารถตรวจสอบเล่มนี้ได้

docker volume inspect pgdata

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

8
แสดงความคิดเห็นสายไปนิด docker-compose down -vแต่จะไม่ล้างข้อมูลนี้ถ้าผมทำ และวิธีแก้ปัญหาคืออะไร?
Sid

3
@Sid ใช่มันจะ! เพียงระวังตัวเลือกนี้
olidem

1
ดังนั้นเมื่อเทียบท่า [เขียน] เสียงจะไม่คงอยู่อีกต่อไป? การล้างข้อมูลเต็มรูปแบบแม้แต่ในระดับเสียงหรือไม่?
Paul

2
@Sid ความเห็นแม้กระทั่งต่อมา แต่คุณสามารถใช้docker-compose down --rmi all โดยไม่ต้อง-vตัวเลือกและมันจะล้างออก "ทุกอย่าง" ยกเว้นปริมาณเช่นภาชนะเครือข่ายภาพ ฯลฯ ฉันทำอย่างนั้นเมื่อปรับใช้ในขณะที่ให้ข้อมูลที่ติดตา
code_dredd

13

ฉันจะหลีกเลี่ยงการใช้เส้นทางสัมพัทธ์ โปรดจำไว้ว่านักเทียบท่านั้นเป็นความสัมพันธ์แบบดีมอน / ลูกค้า

เมื่อคุณกำลังดำเนินการเขียนมันเป็นเพียงแค่การแบ่งออกเป็นคำสั่งไคลเอนต์นักเทียบท่าต่างๆซึ่งจะถูกส่งผ่านไปยังภูต ซึ่ง./databaseสัมพันธ์กับdaemonไม่ใช่ไคลเอ็นต์

ตอนนี้ทีมนักพัฒนาซอฟต์แวร์ของนักเทียบท่าจะมีปัญหานี้มาบ้างแล้ว แต่สิ่งที่สำคัญที่สุดคือมันสามารถมีผลลัพธ์ที่ไม่คาดคิดได้บ้าง

กล่าวโดยย่อคืออย่าใช้เส้นทางที่สัมพันธ์กัน


ขอบคุณสำหรับคำตอบนี้! น่าเศร้าที่ฉันไม่คิดว่ามันทำงานได้ ฉันเปลี่ยนบรรทัดเป็นพา ธ สัมบูรณ์และหลังจากแทรกข้อมูลdatabase/dataโฟลเดอร์ยังว่างเปล่า = (
Alex Lenail

เคลำดับต่อไปคือการรันdocker inspectบนคอนเทนเนอร์และตรวจสอบให้แน่ใจว่าคอนเทนเนอร์นั้นรับรู้ถึงโวลุ่ม (ในกรณีที่การเขียนสับสนหรือบางอย่าง) (หมายเหตุ: นักเทียบท่าตรวจสอบสามารถมีข้อมูลที่ละเอียดอ่อนได้ดังนั้นอย่าวางที่นี่โดยไม่ต้อง munging ;-) หลังจากนั้นมันเป็นเรื่องของการตรวจสอบการอนุญาต (แม้ว่าปกติจะแสดงข้อผิดพลาด)
Nick Burke

Aha! @Nick Burke ฉันคิดว่าคุณได้พบบางสิ่ง ฉันได้อัปเดตคำถามแล้ว
Alex Lenail

2

ฉันคิดว่าคุณเพียงแค่ต้องสร้างวอลลุ่มนอก Docker ก่อนด้วย a docker create -v /location --nameแล้วนำมันกลับมาใช้ใหม่

และตามเวลาที่ฉันเคยใช้นักเทียบท่าจำนวนมากมันเป็นไปไม่ได้เลยที่จะใช้โวลุ่มตัวต่อแบบคงที่ที่มีคำจำกัดความตัวเรียงลำดับไฟล์ดังนั้นคำแนะนำของฉันคือลองบรรทัดคำสั่ง (ในที่สุดก็ใช้สคริปต์)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.