web-dev-qa-db-fra.com

Comment conserver des données dans une base de données postgres dockerisée à l'aide de volumes

Mon fichier de composition de docker contient trois conteneurs, Web, nginx et postgres. Postgres ressemble à ceci:

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

Mon but est de monter un volume qui correspond à un dossier local appelé ./database à l'intérieur du conteneur postgres sous le nom de /var/lib/postgres. Lorsque je démarre ces conteneurs et que j'insère des données dans postgres, je vérifie que /var/lib/postgres/data/base/ est plein des données que j'ajoute (dans le conteneur postgres), mais dans mon système local, ./database ne récupère qu'un data le dossier qu'il contient, c'est-à-dire que ./database/data est créé, mais qu'il est vide. Pourquoi?

Remarques:

MISE À JOUR 1

Selon la suggestion de Nick, j'ai fait un docker inspect et j'ai trouvé:

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

Ce qui donne l'impression que les données sont volées par un autre volume que je n'ai pas codé moi-même. Je ne sais pas pourquoi. Est-ce que l'image postgres crée ce volume pour moi? Si tel est le cas, existe-t-il un moyen d'utiliser ce volume à la place du volume que je monte au redémarrage? Sinon, existe-t-il un bon moyen de désactiver cet autre volume et d'utiliser le mien, ./database?

MISE À JOUR 2

J'ai trouvé la solution, merci à Nick! (et un autre ami) Réponse ci-dessous.

151
Alex Lenail

Curieusement, la solution a fini par être de changer

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

à

volumes:
  - ./postgres-data:/var/lib/postgresql/data
199
Alex Lenail

Vous pouvez créer un commun volume pour toutes les données Postgres

 docker volume create pgdata

ou vous pouvez le définir sur le fichier de composition

   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:

Il créera le nom du volume pgdata et montera ce volume sur le chemin du conteneur.

Vous pouvez inspecter ce volume

docker volume inspect pgdata

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

Je voudrais éviter d'utiliser un chemin relatif. Rappelez-vous que docker est une relation démon/client.

Lorsque vous exécutez la composition, il s’agit essentiellement de décomposer en diverses commandes du client Docker, qui sont ensuite transmises au démon. Ce ./database est alors relatif au démon , pas au client.

Maintenant, l'équipe de développement de docker a des échanges sur ce problème , mais le résultat est qu'elle peut avoir des résultats inattendus.

En bref, n'utilisez pas de chemin relatif, utilisez un chemin absolu.

11
Nick Burke

Je pense que vous devez simplement créer votre volume en dehors du menu fixe à l’aide d’un docker create -v /location --name, puis le réutiliser.

Et au moment où j’utilisais souvent docker, il n’était pas possible d’utiliser un volume fixe de docker avec une définition de dockerfile; ma suggestion est donc d’essayer la ligne de commande (éventuellement avec un script).

2
Joel B