Sauvegarder / restaurer une base de données PostgreSQL dockérisée

156

J'essaie de sauvegarder / restaurer une base de données PostgreSQL comme expliqué sur le site Web de Docker, mais les données ne sont pas restaurées.

Les volumes utilisés par l'image de la base de données sont:

VOLUME  ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]

et le CMD est:

CMD ["/usr/lib/postgresql/9.3/bin/postgres", "-D", "/var/lib/postgresql/9.3/main", "-c", "config_file=/etc/postgresql/9.3/main/postgresql.conf"]

Je crée le conteneur DB avec cette commande:

docker run -it --name "$DB_CONTAINER_NAME" -d "$DB_IMAGE_NAME"

Ensuite, je connecte un autre conteneur pour insérer manuellement des données:

docker run -it --rm --link "$DB_CONTAINER_NAME":db "$DB_IMAGE_NAME" sh -c 'exec bash'
psql -d test -h $DB_PORT_5432_TCP_ADDR
# insert some data in the db
<CTRL-D>
<CTRL-D>

L'archive tar est alors créée:

$ sudo docker run --volumes-from "$DB_CONTAINER_NAME" --rm -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /etc/postgresql /var/log/postgresql /var/lib/postgresql

Maintenant, je supprime le conteneur utilisé pour la base de données et en crée un autre, avec le même nom, et j'essaye de restaurer les données insérées avant:

$ sudo docker run --volumes-from "$DB_CONTAINER_NAME" --rm -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar 

Mais les tables sont vides, pourquoi les données ne sont-elles pas correctement restaurées?

Carl Levasseur
la source

Réponses:

458

Sauvegardez vos bases de données

docker exec -t your-db-container pg_dumpall -c -U postgres > dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql

Restaurez vos bases de données

cat your_dump.sql | docker exec -i your-db-container psql -U postgres
Quatrième
la source
2
Oui, c'est la façon postgres de le faire, mais je pense que la méthode docker devrait toujours être préférée lorsque vous l'utilisez
Carl Levasseur
42
Pour économiser de l'espace sur le disque, vous pouvez diriger le vidage vers gzip: docker exec -t your-db-container pg_dumpall -c -U postgres | gzip > /var/data/postgres/backups/dump_date +% d-% m-% Y "_"% H_% M_% S.gz
Tarion
1
Décompressez simplement les données avant de les restaurer. Pour le faire en une seule ligne, vous devrez remplacer le cat your_dump.sqlpar la commande unzip et le diriger au lieu du catrésultat vers docker exec.
Tarion
2
Le format de la date est foiré, alors vérifiez-le avant de copier et coller.
vidstige
1
Pour ceux qui ne pourraient pas comprendre comment faire fonctionner le formatage de la date: docker exec -t your-db-container pg_dumpall -c -U postgres | gzip > ./tmp/dump_$(date +"%Y-%m-%d_%H_%M_%S").gz
user1230795
18

Je pense que vous pouvez également utiliser un conteneur de sauvegarde potgres qui sauvegarderait vos bases de données dans un délai donné.

  pgbackups:
    container_name: Backup
    image: prodrigestivill/postgres-backup-local
    restart: always
    volumes:
      - ./backup:/backups
    links:
      - db:db
    depends_on:
      - db
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_DB=${DB_NAME} 
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_EXTRA_OPTS=-Z9 --schema=public --blobs
      - SCHEDULE=@every 0h30m00s
      - BACKUP_KEEP_DAYS=7
      - BACKUP_KEEP_WEEKS=4
      - BACKUP_KEEP_MONTHS=6
      - HEALTHCHECK_PORT=81
Tharindu Pradeep
la source
1
Fonctionne parfaitement ! Merci
CaM2091
15

D'accord, j'ai compris ça. Postgresql ne détecte pas les changements dans le dossier / var / lib / postgresql une fois qu'il est lancé, du moins pas le genre de changements que je veux qu'il détecte.

La première solution consiste à démarrer un conteneur avec bash au lieu de démarrer directement le serveur postgres, à restaurer les données, puis à démarrer le serveur manuellement.

La deuxième solution consiste à utiliser un conteneur de données. Je n'avais pas compris avant, maintenant je le sais. Ce conteneur de données permet de restaurer les données avant de démarrer le conteneur postgres. Ainsi, lorsque le serveur postgres démarre, les données sont déjà là.

Carl Levasseur
la source
1
le flocker ou le convoi peut aider à traiter les conteneurs de données.
Forth
24
Veuillez remplir plus de détails. Cela ressemble plus à une esquisse d'une solution qu'à une solution réelle
nafg
5

Une autre approche (basée sur docker-postgresql-workflow )

Base de données locale en cours d'exécution (pas dans le docker, mais la même approche fonctionnerait) pour exporter:

pg_dump -F c -h localhost mydb -U postgres export.dmp

Base de données de conteneurs à importer:

docker run -d -v /local/path/to/postgres:/var/lib/postgresql/data postgres #ex runs container as `CONTAINERNAME` #find via `docker ps`
docker run -it --link CONTAINERNAME:postgres  --volume $PWD/:/tmp/  postgres  bash -c 'exec pg_restore -h postgres -U postgres -d mydb -F c /tmp/sonar.dmp'
sjakubowski
la source
1
cela a fonctionné pour moi: pg_dump mydb -U postgres > export.psqldans le conteneur de docker bash
Sepultura
3

J'ai eu ce problème en essayant d'utiliser un db_dump pour restaurer un db. J'utilise normalement dbeaver pour restaurer - cependant j'ai reçu un vidage psql, donc j'ai dû trouver une méthode pour restaurer en utilisant le conteneur docker.

La méthodologie recommandée par Forth et éditée par Soviut a fonctionné pour moi:

cat your_dump.sql | docker exec -i your-db-container psql -U postgres -d dbname

(puisqu'il s'agissait d'un seul db dump et non de plusieurs db, j'ai inclus le nom)

Cependant, pour que cela fonctionne, je devais également accéder au virtualenv dans lequel se trouvaient le conteneur et le projet du docker. Cela m'a échappé un peu avant de le comprendre, car je recevais l'erreur de docker suivante.

read unix @->/var/run/docker.sock: read: connection reset by peer

Cela peut être causé par le fichier /var/lib/docker/network/files/local-kv.db. Je ne connais pas l'exactitude de cette déclaration: mais je crois que je voyais cela car je n'utilise pas docker localement, donc n'avait pas ce fichier, qu'il cherchait, en utilisant la réponse de Forth.

J'ai ensuite navigué vers le répertoire correct (avec le projet) activé le virtualenv, puis exécuté la réponse acceptée. Boom, fonctionnait comme un top. J'espère que cela aide quelqu'un d'autre!

activer la réalité
la source
1

C'est la commande qui a fonctionné pour moi.

cat your_dump.sql | sudo docker exec -i {docker-postgres-container} psql -U {user} -d {database_name}

par exemple

cat table_backup.sql | docker exec -i 03b366004090 psql -U postgres -d postgres

Référence : Solution donnée par GMartinez-Sisti dans cette discussion. https://gist.github.com/gilyes/525cc0f471aafae18c3857c27519fc4b

Jacob Nelson
la source
1

cat db.dump | docker exec ...façon n'a pas fonctionné pour mon vidage (~ 2 Go). Cela a pris quelques heures et s'est soldé par une erreur de mémoire insuffisante.

Au lieu de cela, j'ai cp'ed dump dans le conteneur et pg_restore'ed de l'intérieur.

En supposant que l'ID du conteneur est CONTAINER_IDet que le nom de la base de données est DB_NAME:

# copy dump into container
docker cp local/path/to/db.dump CONTAINER_ID:/db.dump

# shell into container
docker exec -it CONTAINER_ID bash

# restore it from within
pg_restore -U postgres -d DB_NAME --no-owner -1 /db.dump
Alex Fedoseev
la source
0

dksnap( https://github.com/kelda/dksnap ) automatise le processus d'exécution pg_dumpallet de chargement du dump via/docker-entrypoint-initdb.d .

Il vous montre une liste de conteneurs en cours d'exécution et vous choisissez celui que vous souhaitez sauvegarder. L'artefact résultant est une image Docker standard, vous pouvez donc la docker runpartager ou la partager en la poussant vers un registre Docker.

(avertissement: je suis responsable du projet)

Kevin Lin
la source
0

La commande ci-dessous peut être utilisée pour prendre le vidage du conteneur postgress de docker

docker exec -t <postgres-container-name> pg_dump --no-owner -U <db-username> <db-name> > file-name-to-backup-to.sql
Shubham
la source