Cara mempertahankan data dalam database postgresisasi dengan menggunakan volume

205

File penulisan docker saya memiliki tiga kontainer, web, nginx, dan postgres. Postgres terlihat seperti ini:

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

Tujuan saya adalah memasang volume yang sesuai dengan folder lokal yang disebut ./databasedi dalam wadah postgres /var/lib/postgres. Ketika saya mulai wadah ini dan memasukkan data ke postgres, saya memverifikasi bahwa /var/lib/postgres/data/base/penuh dengan data yang saya tambahkan (dalam wadah postgres), tetapi dalam sistem lokal saya, ./databasehanya mendapat datafolder di dalamnya, yaitu ./database/datadibuat, tetapi kosong . Mengapa?

Catatan:

PEMBARUAN 1

Atas saran Nick, saya melakukan docker inspectdan menemukan:

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

Yang membuatnya tampak seperti data sedang dicuri oleh volume lain saya tidak kode sendiri. Tidak yakin kenapa seperti itu. Apakah gambar postgres membuat volume itu untuk saya? Jika demikian, apakah ada cara untuk menggunakan volume itu alih-alih volume yang saya pasang saat memulai ulang? Jika tidak, apakah ada cara yang baik untuk menonaktifkan volume lain itu dan menggunakan volume saya sendiri ./database?

PEMBARUAN 2

Saya menemukan solusinya, terima kasih kepada Nick! (dan teman lain) Jawab di bawah.

Alex Lenail
sumber
apakah Anda sudah menjalankan initdbbaris perintah untuk menginisialisasi cluster database Anda?
Sebastian Webber
Apakah Anda yakin subdirektori data Anda benar-benar kosong? Mungkin memiliki izin akses khusus.
Yaroslav Stavnichiy
Terima kasih telah kembali padaku begitu cepat! Saya menggunakan aplikasi labu, jadi saya from app import dbdan db.create_all()dari docker runsetelah memulai wadah. Saya tidak initdblangsung dari baris perintah.
Alex Lenail
1
@YaroslavStavnichiy Saya tidak tahu bagaimana cara memeriksa sudo su -dan melihat ke dalam ./database/data. Tidak ada apa-apa di sana sejauh yang saya tahu.
Alex Lenail
Seseorang mungkin menemukan ini berguna: contoh menulis file postgres bertahan, pencarian elastis dan data media, stackoverflow.com/a/56475980/5180118
ArdentLearner

Jawaban:

254

Anehnya, solusinya akhirnya berubah

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

untuk

volumes:
  - ./postgres-data:/var/lib/postgresql/data
Alex Lenail
sumber
45
Hanya "mengapa" cepat untuk jawaban ini (yang berfungsi). Per orang postgres, direktori data default adalah /var/lib/postgresql/data- Anda dapat membaca catatan variabel PGDATA di sini: store.docker.com/images/…
Matt Pavelle
2
Dalam pertanyaan di atas, OP mengatakan itu bekerja untuknya tanpa / data pada akhirnya. Apakah itu benar?
Sid
2
Dan tambahkan direktori lokal ke .dockerignorefile Anda , terutama jika Anda akan memangkas ini menjadi gambar produksi. Lihat codefresh.io/blog/not-ignore-dockerignore untuk diskusi.
dsz
4
ini masih tidak bekerja untuk saya (mac os x high sierra)
olidem
1
@ OlliD-Metz saya harus melakukan docker rm my_postgres_container_1sebelum berhasil (juga High Sierra).
kaya
101

Anda dapat membuat volume umum untuk semua data Postgres

 docker volume create pgdata

atau Anda dapat mengaturnya ke file penulisan

   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:

Ini akan membuat pgdata nama volume dan me-mount volume ini ke jalur penampung.

Anda dapat memeriksa volume ini

docker volume inspect pgdata

// output will be
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
        "Name": "pgdata",
        "Options": {},
        "Scope": "local"
    }
]
Nishchit Dhanani
sumber
8
Mengomentari sedikit terlambat, tetapi tidakkah ini menghapus data jika saya melakukan docker-compose down -v. Dan apa solusinya?
Sid
3
@ Id, ya, itu akan! Berhati-hatilah dengan opsi ini.
olidem
1
jadi dengan docker-compose [down] volumenya tidak lagi bertahan? Apakah pembersihan penuh bahkan dari volume?
Paul
2
@Sid Mengomentari bahkan kemudian, tetapi Anda dapat menggunakan docker-compose down --rmi all tanpa yang -vpilihan dan itu akan membersihkan "segala sesuatu" kecuali volume, yaitu kontainer, jaringan, gambar, dll saya melakukan itu ketika deploying sementara memungkinkan data ketekunan.
code_dredd
13

Saya akan menghindari menggunakan jalur relatif. Ingatlah bahwa buruh pelabuhan adalah hubungan daemon / klien.

Ketika Anda menjalankan penulisan, itu pada dasarnya hanya memecah menjadi berbagai perintah klien buruh pelabuhan, yang kemudian diteruskan ke daemon. Itu ./databasekemudian relatif terhadap daemon , bukan klien.

Sekarang, tim pengembang buruh pelabuhan memiliki beberapa bolak-balik tentang masalah ini , tetapi intinya adalah ia dapat memiliki beberapa hasil yang tidak terduga.

Singkatnya, jangan gunakan jalur relatif, gunakan jalur absolut.

Nick Burke
sumber
Terima kasih atas jawaban ini! Sayangnya, saya pikir itu tidak berhasil. Saya mengubah jalur menjadi jalur absolut, dan setelah memasukkan data, database/datafolder tersebut masih kosong = (
Alex Lenail
K. Selanjutnya adalah menjalankan docker inspectpada wadah dan memastikan bahwa wadah mengetahui volume (kalau-kalau menulis bingung atau sesuatu). (catatan: buruh pelabuhan dapat memiliki data sensitif, jadi jangan tempel di sini tanpa munging ;-) Setelah itu, masalah memeriksa izin (meskipun itu biasanya akan menunjukkan kesalahan)
Nick Burke
Aha! @Nick Burke saya pikir Anda telah menemukan sesuatu. Saya telah memperbarui pertanyaan.
Alex Lenail
2

Saya pikir Anda hanya perlu membuat volume Anda di luar buruh pelabuhan pertama dengan docker create -v /location --namedan kemudian menggunakannya kembali.

Dan pada saat saya sering menggunakan buruh pelabuhan, itu tidak mungkin untuk menggunakan volume buruh pelabuhan statis dengan definisi dockerfile jadi saran saya adalah untuk mencoba baris perintah (akhirnya dengan skrip).

Joel B
sumber