web-dev-qa-db-fra.com

Comment utiliser un conteneur PostgreSQL avec des données existantes?

J'essaie de configurer un conteneur PostgreSQL ( https://hub.docker.com/_/postgres/ ). J'ai des données d'une instance actuelle de PostgreSQL. Je l'ai copié de /var/lib/postgresql/data et souhaitez le définir en tant que volume dans un conteneur PostgreSQL.

Ma partie du fichier docker-compose.yml à propos de PostgreSQL:

db:
    image: postgres:9.4
    ports:
        - 5432:5432
    environment:
        POSTGRES_PASSWORD: postgres
        POSTGRES_USER: postgres
        PGDATA : /var/lib/postgresql/data
    volumes:
        - /projects/own/docker_php/pgdata:/var/lib/postgresql/data

Lorsque je crée un menu fixe, je reçois le message suivant:

db_1  | initdb: directory "/var/lib/postgresql/data" exists but is not empty
db_1  | If you want to create a new database system, either remove or empty
db_1  | the directory "/var/lib/postgresql/data" or run initdb
db_1  | with an argument other than "/var/lib/postgresql/data".

J'ai essayé de créer ma propre image à partir du conteneur. Mon fichier Docker est donc:

FROM postgres:9.4
COPY pgdata /var/lib/postgresql/data

Mais j'ai la même erreur, qu'est-ce que je fais mal?

Mise à jour

J'ai obtenu SQL en utilisant pg_dumpall et je l'ai mis dans /docker-entrypoint-initdb.d, mais ce fichier est exécuté à chaque fois que je fais docker-compose up.

37
Albert Tobac

Pour compléter la réponse de irakli, voici une solution mise à jour:

  • utiliser la version plus récente du fichier Docker Compose
  • section séparée volumes
  • paramètres supplémentaires supprimés

docker-compose.yml

version: '2'

services:
  postgres9:
    image: postgres:9.4
    expose:
      - 5432
    volumes:
      - data:/var/lib/postgresql/data

volumes:
  data: {}

démo

Démarrer le serveur de base de données Postgres:

$ docker-compose up

Afficher toutes les tables de la base de données. Dans un autre terminal, parlez au Postgres du conteneur:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c '\z'

Cela ne montrera rien, car la base de données est vide. Créer une table:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c 'create table beer()'

Répertoriez le tableau nouvellement créé:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c '\z'

                         Access privileges
 Schema |   Name    | Type  | Access privileges | Column access privileges 
--------+-----------+-------+-------------------+--------------------------
 public | beer      | table |                   | 

Yay! Nous avons maintenant démarré une base de données Postgres utilisant un volume de stockage partagé et y avons stocké des données. La prochaine étape consiste à vérifier que les données restent après l’arrêt du serveur.

Maintenant, tuez le conteneur du serveur Postgres:

$ docker-compose stop

Relancez le conteneur Postgres:

$ docker-compose up

Nous nous attendons à ce que le serveur de base de données réutilise le stockage, de sorte que nos données très importantes sont toujours là. Vérifier:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c '\z'
                         Access privileges
 Schema |   Name    | Type  | Access privileges | Column access privileges 
--------+-----------+-------+-------------------+--------------------------
public | beer      | table |                   | 

Nous avons utilisé avec succès un fichier Docker Compose d'un nouveau style pour exécuter une base de données Postgres à l'aide d'un volume de données externe, et nous avons vérifié qu'il conserve nos données en toute sécurité.

stocker des données

Tout d’abord, faites une sauvegarde en stockant nos données sur l’hôte:

$ docker exec -it $(docker-compose ps -q postgres9 ) pg_dump -Upostgres > backup.sql

Zappez nos données de la base de données d'invités:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c 'drop table beer'

Restaurez notre sauvegarde (stockée sur l'hôte) dans le conteneur Postgres.

Remarque: utilisez "exec -i", not "-it", sinon vous obtiendrez une erreur "le périphérique d'entrée n'est pas un téléscripteur".

$ docker exec -i $(docker-compose ps -q postgres9 ) psql -Upostgres < backup.sql

Répertoriez les tables pour vérifier que la restauration avait bien fonctionné:

$ docker exec -it $(docker-compose ps -q postgres9 ) psql -Upostgres -c '\z'
                         Access privileges
Schema |   Name    | Type  | Access privileges | Column access privileges 
--------+-----------+-------+-------------------+--------------------------
public | beer      | table |                   | 

En résumé, nous avons vérifié que nous pouvons démarrer une base de données, que les données sont conservées après un redémarrage et que nous pouvons restaurer une sauvegarde à partir de l'hôte.

Merci Tomasz!

50
johntellsall

Il semble que l'image PostgreSQL ait des problèmes avec les volumes montés. FWIW, il s’agit probablement davantage d’un problème lié à PostgreSQL que Dockers, mais cela n’a pas d’importance, car le montage de disques n’est en aucun cas une méthode recommandée pour la persistance de fichiers de base de données.

Vous devriez plutôt créer des conteneurs Docker contenant uniquement des données. Comme ça:

postgres9:
  image: postgres:9.4
  ports:
    - 5432:5432
  volumes_from:
    - pg_data
  environment:
    POSTGRES_PASSWORD: postgres
    POSTGRES_USER: postgres
    PGDATA : /var/lib/postgresql/data/pgdata

pg_data:
  image: Alpine:latest
  volumes:
    - /var/lib/postgresql/data/pgdata
  command: "true"

que j'ai testé et a bien fonctionné. Pour en savoir plus sur les conteneurs de données uniquement, cliquez ici: Pourquoi les conteneurs de données Docker (volumes!) Sont-ils bons

En ce qui concerne: comment importer les données initiales, vous pouvez soit:

  1. docker cp, dans le conteneur de données de la configuration uniquement, ou
  2. Utilisez un cliché SQL des données au lieu de déplacer des fichiers binaires (ce que je ferais).
10
irakli