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


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.