Як зберегти дані в докерізованій базі даних постгрес, використовуючи томи


204

Мій файл докер-композиції містить три контейнери, веб, 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

За пропозицією Ніка, я зробив 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": ""
        }
    ],

З-за чого здається, що дані викрадаються іншим томом, який я не кодував. Не впевнений, чому це так. Чи створює для мене зображення постгресу саме цього обсягу? Якщо так, чи є спосіб використовувати цей том замість гучності, яку я монтую під час перезавантаження? В іншому випадку, чи є хороший спосіб відключити цей інший том і використовувати мій власний ./database,?

ОНОВЛЕННЯ 2

Я знайшов рішення, завдяки Ніку! (та інший друг) Відповідь нижче.


Ви вже запускаєте initdbкомандний рядок для ініціалізації кластера вашої бази даних?
Себастьян Вебер

Ви впевнені, що підкаталог ваших даних справді порожній? Він може мати спеціальні дозволи доступу.
Ярослав Ставничий

Дякуємо, що повернулися до мене так швидко! Я використовую додаток опоки, так що я from app import dbі db.create_all()від А docker runпісля запуску контейнерів. Я не initdbпрямо з командного рядка.
Олексій Ленейл

1
@YaroslavStavnichiy Я не знаю, як ще це перевірити, ніж sudo su -заглянути ./database/data. Нічого там немає, наскільки я можу сказати.
Алекс Ленейл

Хто - то може виявитися корисним: зразок файлу зберігається Postgres створення повідомлення , пружний пошук і мультимедійних дані, stackoverflow.com/a/56475980/5180118
ArdentLearner

Відповіді:


252

Як не дивно, рішення вирішило змінитись

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

до

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

45
Просто швидке "чому" для цієї відповіді (яка працює). Відповідно до людей, що відповідають публікаціям, каталог даних за замовчуванням /var/lib/postgresql/data- ви можете прочитати примітки змінної PGDATA тут: store.docker.com/images/…
Matt Pavelle

2
У вищезазначеному запиті ОП каже, що це працювало на нього без даних / наприкінці. Це правильно?
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до того, як це спрацювало (також Висока Сьєрра).
багатий

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, так, так і буде! Будьте обережні з цим варіантом.
олідем

1
так що з docker-compose [вниз] гучність більше не зберігається? Є повне очищення рівним обсягом?
Павло

2
@Sid Коментуючи навіть пізніше, але ви можете використовувати docker-compose down --rmi all без цього -vваріанту, і це очистить "все", крім томів, тобто контейнерів, мереж, зображень тощо. Я це роблю під час розгортання, дозволяючи зберегти дані.
code_dredd

13

Я б уникнув використання відносного шляху. Пам'ятайте, що докер - це відносини демона / клієнта.

Коли Ви виконуєте композицію, це, по суті, просто розбиття на різні команди докер-клієнтів, які потім передаються демону. Те ./databaseє , то по відношенню до демона , а не клієнт.

Тепер команда докерських розробників має певні результати в цьому питанні , але суть полягає в тому, що це може мати неочікувані результати.

Словом, не використовуйте відносний шлях, використовуйте абсолютний шлях.


Дякую за цю відповідь! На жаль, я не думаю, що це спрацювало. Я змінив рядок на абсолютний шлях, і після вставки даних database/dataпапка залишається порожньою = (
Alex Lenail

K. Далі слід запустити docker inspectконтейнер і переконатися, що контейнер знає об'єм (на випадок, якщо композиція плутається чи щось). (зауважте: докер перевірка може мати конфіденційні дані, тому не вставляйте їх сюди, не змінюючи їх ;-) Після цього справа в тому, щоб перевірити дозволи (хоча це, як правило, показувало б помилку)
Нік Берк

Ага! @Nick Burke Я думаю, що ти щось знайшов. Я оновив питання.
Олексій Ленейл

2

Я думаю, що вам просто потрібно створити свій об'єм за межами докера спочатку з a, docker create -v /location --nameа потім повторно використовувати його.

На той час, коли я багато використовував docker, не вдалося використати статичний том докера з визначенням dockerfile, тому моя пропозиція - спробувати командний рядок (зрештою, зі скриптом).


0

У мене було таке ж питання днями. Я мій випадок був просто помилковим: "postgresql" має лише одне записування "s" я два (postgressql): $.


Що змушує вас думати, що той самий друкарський випадок стався з особою, яка поставила запитання, враховуючи, що помилка друку, на яку ви посилалися, не відображається в їх запитанні?
Джейсон Аллер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.