Как сохранить данные в докеризованной базе данных postgres, используя тома


205

В моем файле docker compose есть три контейнера: web, nginx и postgres. Postgres выглядит так:

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

Моя цель - смонтировать том, который соответствует локальной папке, называемой ./databaseвнутри контейнера postgres as /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": ""
        }
    ],

Это создает впечатление, что данные украдены другим томом, который я сам не кодировал. Не уверен, почему это так. Является ли изображение postgres тем объемом для меня? Если да, есть ли способ использовать этот том вместо тома, который я монтирую при перезапуске? Иначе, есть ли хороший способ отключить этот другой том и использовать мой собственный ./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

Ответы:


254

Как ни странно, решение закончилось тем, что изменилось

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

в

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

45
Просто быстрое «почему» для этого ответа (который работает). По мнению пользователей postgres, каталог данных по умолчанию /var/lib/postgresql/data- вы можете прочитать примечания к переменным PGDATA здесь: store.docker.com/images/…
— Мэтт Павел

2
В вышеупомянутом вопросе OP говорит, что он работал для него без / data в конце. Это правильно?
— Сид

2
И добавьте локальный каталог в свой .dockerignoreфайл, особенно если вы когда-нибудь добавите его в рабочий образ. См. Codefresh.io/blog/not-ignore-dockerignore для обсуждения.
— ДСЗ

4
это все еще не работает для меня (Mac OS X High
— Sierra

1
@ OlliD-Metz Я должен был сделать, docker rm my_postgres_container_1прежде чем это сработало (также High Sierra).
— Богатые

101

Вы можете создать общий том для всех данных 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. И каково решение этого?
— Сид

3
@ Сид, да, будет! Просто будьте осторожны с этой опцией.
— olidem

1
так с docker-compose [down] громкость больше не сохраняется? Есть ли полная очистка даже от объема?
— Пол

2
@Sid Комментируя даже позже, но вы можете использовать docker-compose down --rmi all без по -vвыбору , и она будет очистить «все» за исключением объемов, т.е. контейнеров, сети, изображения и т.д. Я , что при развертывании, позволяя сохранение данных.
— code_dredd

13

Я бы не использовал относительный путь. Помните, что docker - это отношения демон / клиент.

Когда вы выполняете compose, он просто разбивается на различные клиентские команды docker, которые затем передаются демону. Это ./databaseотносится к демону , а не к клиенту.

Теперь у команды разработчиков докеров есть кое-что по этому вопросу , но суть в том, что у нее могут быть неожиданные результаты.

Короче говоря, не используйте относительный путь, используйте абсолютный путь.


Спасибо за этот ответ! К сожалению, я не думаю, что это сработало. Я изменил строку на абсолютный путь, и после вставки данных database/dataпапка все еще пуста = (
— Alex Lenail

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

Ага! @ Ник Берк Я думаю, ты что-то нашел. Я обновил вопрос.
— Алекс Ленаил

2

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

И к тому времени, когда я часто использовал docker, было невозможно использовать статический том docker с определением dockerfile, поэтому я предлагаю попробовать командную строку (в конце концов, с помощью скрипта).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.