Comment gérer le stockage persistant (par ex. bases de données) dans Docker

comment les gens gèrent-ils le stockage permanent de vos conteneurs Docker?

j'utilise actuellement cette approche: construire l'image, par exemple pour PostgreSQL, puis démarrer le conteneur avec

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

IMHO, qui a l'inconvénient, que je ne dois jamais (par accident) supprimer le conteneur "c0dbc34fd631".

une autre idée serait de monter les volumes hôtes "- v" dans le conteneur, cependant, le userid dans le conteneur ne correspond pas nécessairement au userid de l'hôte, et les permissions peuvent alors être faussées.

Note: au lieu de --volumes-from 'cryptic_id' vous pouvez également utiliser --volumes-from my-data-containermy-data-container est un nom que vous avez attribué à un conteneur de données seulement, par exemple docker run --name my-data-container ... (voir la réponse acceptée)

857
demandé sur Peter Mortensen 2013-08-28 23:45:44

14 réponses

Docker 1.9.0 et plus

Utiliser "1519140920 de volume" API

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

cela signifie que le modèle de conteneur ne comportant que des données doit être abandonné au profit des nouveaux volumes.

en fait L'API de volume est seulement un meilleur moyen d'atteindre ce qui était le modèle de conteneur de données.

si vous créez un conteneur avec un Docker -v volume_name:/container/fs/path créera automatiquement un volume nommé pour vous qui pouvez:

  1. Être énumérés par le docker volume ls
  2. doit être identifié par le docker volume inspect volume_name
  3. Sauvegardé dans un répertoire normal
  4. sauvegardé comme avant par une --volumes-from connexion

la nouvelle API de volume ajoute une commande utile qui vous permet d'identifier les volumes pendants:

docker volume ls -f dangling=true

et ensuite l'enlever par son nom:

docker volume rm <volume name>

comme le souligne @mpugach dans les commentaires, vous pouvez vous débarrasser de tous les volumes pendants avec une jolie doublure:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune

Docker 1.8.x et inférieur

l'approche qui semble fonctionner le mieux pour la production est d'utiliser un conteneur de données seulement .

le conteneur de données seulement est exécuté sur une image barebones et ne fait effectivement rien, sauf exposer un volume de données.

alors vous pouvez exécuter n'importe quel autre conteneur pour avoir accès aux volumes de conteneur de données:

docker run --volumes-from data-container some-other-container command-to-execute
  • Ici vous pouvez obtenir une bonne image de la façon d'organiser les différents conteneurs.
  • Ici il y a un bon aperçu de la façon dont les volumes de travail.

Dans ce blog il y est une bonne description de la soi-disant conteneur comme modèle de volume qui clarifie le point principal d'avoir conteneurs données seulement .

Docker documentation a maintenant la description DÉFINITIVE de la conteneur de volume/s modèle.

ci-dessous est la procédure de sauvegarde/restauration pour Docker 1.8.x et ci-dessous.

BACKUP:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
  • -- rm: retirer le conteneur lorsqu'il sort
  • --des volumes de DONNÉES: fixer les volumes partagés par le conteneur de DONNÉES
  • -v $(pwd):/sauvegarde: lier monter le répertoire courant dans le récipient; pour écrire le fichier tar
  • busybox: une petite image plus simple-bon pour un entretien rapide
  • tar cvf /backup/sauvegarde.tar / data: crée un fichier tar non compressé de tous les fichiers du répertoire / data

"1519420920 de RESTAURATION":

# Create a new data container
$ sudo docker run -v /data -name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# Compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt

voici un bel article de L'excellent Brian Goff expliquant pourquoi il est bon d'utiliser la même image pour un conteneur et un conteneur de données.

899
répondu tommasop 2018-07-25 04:47:05

Dans Docker version v1.0 , la liaison d'un montage d'un fichier ou d'un répertoire sur la machine hôte peut être fait par la commande:

$ docker run -v /host:/container ...

le volume ci-dessus pourrait être utilisé comme un stockage persistant sur l'hôte courant Docker.

60
répondu amitmula 2018-07-25 04:50:45

depuis Docker Compose 1.6, il y a maintenant un meilleur support pour les volumes de données dans Docker Compose. Le fichier de composition suivant créera une image de données qui persistera entre les redémarrages (ou même la suppression) des conteneurs parents:

Voici l'annonce du blog: Compose 1.6: nouveau fichier de composition pour définir les réseaux et les volumes

voici un exemple de fichier de composition:

version: "2"

services:
  db:
    restart: on-failure:10
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
  web:
    restart: on-failure:10
    build: .
    command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

volumes:
  db-data:

pour autant que je puisse comprendre: cela créera un conteneur de volume de données ( db_data ) qui persistera entre les redémarrages.

si vous exécutez: docker volume ls vous devriez voir votre volume listé:

local               mypthonapp_db-data
...

vous pouvez obtenir plus de détails sur le volume de données:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

Quelques tests:

# Start the containers
docker-compose up -d

# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...

# Stop and remove the containers:
docker-compose stop
docker-compose rm -f

# Start it back up again
docker-compose up -d

# Verify the data is still there
...
(it is)

# Stop and remove with the -v (volumes) tag:

docker-compose stop
docker=compose rm -f -v

# Up again ..
docker-compose up -d

# Check the data is still there:
...
(it is).

Notes:

  • vous pouvez également spécifier divers pilotes dans le bloc volumes . Par exemple, vous pouvez spécifier le pilote de Flocker pour db_data:

    volumes:
      db-data:
        driver: flocker
    
  • comme ils améliorent l'intégration entre Docker essaim et docker composer (et peut-être commencer à intégrer Flocker dans L'éco-système Docker (j'ai entendu une rumeur que Docker a acheté Flocker), je pense que cette approche devrait devenir de plus en plus puissant.

Avertissement: Cette approche est prometteuse, et je l'utilise avec succès dans un environnement de développement. J'appréhenderais de l'utiliser dans la production tout de suite!

25
répondu toast38coza 2018-07-25 16:09:15

dans le cas où il n'est pas clair à partir de la mise à jour 5 de la réponse sélectionnée, à partir de Docker 1.9, vous pouvez créer des volumes qui peuvent exister sans être associés à un conteneur spécifique, ce qui rend le modèle" conteneur de données seulement " obsolète.

voir conteneurs de données seulement obsolètes avec docker 1.9.0? #17798 .

je pense que les responsables du Docker ont réalisé que le modèle de conteneur de données était un peu concevoir l'odeur et a décidé de faire des volumes une entité séparée qui peut exister sans un conteneur associé.

15
répondu ben_frankly 2018-07-25 16:03:21

bien qu'il s'agisse encore d'une partie du Docker qui nécessite un peu de travail , vous devez mettre le volume dans le fichier Dockerfile avec l'instruction de VOLUME de sorte que vous n'avez pas besoin de copier les volumes d'un autre conteneur.

qui rendra vos conteneurs moins inter-dépendants et vous n'avez pas à vous soucier de la suppression d'un conteneur affectant un autre.

12
répondu Tim Dorr 2018-07-25 04:48:06

lorsque vous utilisez Docker composer, simplement joindre un volume nommé, par exemple,

version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - db_data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: root
volumes:
  db_data:
9
répondu Czar Pino 2018-07-25 16:17:12

@tommasop la réponse est bonne, et explique la mécanique de l'utilisation des données-seuls les contenants. Mais en tant que quelqu'un qui a d'abord pensé que les conteneurs de données étaient stupides quand on pourrait simplement attacher un volume à l'hôte (comme suggéré par plusieurs autres réponses), mais se rend maintenant compte qu'en fait les conteneurs de données seulement sont assez soignés, je peux suggérer mon propre billet de blog sur ce sujet: pourquoi Docker conteneurs de données (Volumes!) sont bons

Voir aussi: ma réponse à la question " qu'est-Ce que la (meilleure) façon de gérer les autorisations pour Docker volumes partagés? " pour un exemple d'utilisation de conteneurs de données pour éviter des problèmes comme les permissions et la correspondance uid/gid avec l'hôte.

pour répondre à l'une des préoccupations initiales de L'OP: que le conteneur de données ne doit pas être supprimé. Même si le conteneur de données est supprimé, les données elles-mêmes ne seront pas perdus aussi longtemps que conteneur a une référence à ce volume, c'est-à-dire tout conteneur qui a monté le volume via --volumes-from . Ainsi, à moins que tous les conteneurs liés ne soient arrêtés et supprimés (on pourrait considérer cela comme l'équivalent d'un accident rm -fr / ), les données sont sûres. Vous pouvez toujours recréer le conteneur de données en faisant --volumes-from tout conteneur qui a une référence à ce volume.

comme toujours, faites des sauvegardes!

mise à jour: Docker a maintenant des volumes qui peuvent être géré indépendamment des conteneurs, ce qui rend la gestion plus facile.

8
répondu Raman 2018-07-25 04:59:56

si vous voulez déplacer vos volumes autour de vous, vous devriez également regarder flocon .

From the README:

Flocker est un gestionnaire de volume de données et un outil de gestion de cluster de Docker multi-hôtes. Avec elle, vous pouvez contrôler vos données en utilisant les mêmes outils que vous utilisez pour vos applications apatrides en exploitant la puissance de ZFS sur Linux.

Cela signifie que vous pouvez lancez vos bases de données, vos Files d'attente et vos magasins de valeurs clés dans Docker et déplacez-les aussi facilement que le reste de votre application.

7
répondu Johann Romefort 2018-07-25 15:50:08

il y a plusieurs niveaux de gestion des données persistantes, selon vos besoins:

  • Stockez - le sur votre hôte
    • utilisez le drapeau -v host-path:container-path pour persister les données du répertoire des conteneurs dans un répertoire hôte.
    • les sauvegardes / restaurations se produisent en exécutant un conteneur de sauvegarde/restauration (tel que tutumcloud/dockup) monté dans le même répertoire.
  • créer un conteneur de données et monter ses volumes à votre conteneur d'application
    • créez un conteneur qui exporte un volume de données, utilisez --volumes-from pour monter ces données dans votre conteneur d'application.
    • Sauvegarde/restauration de le même que la solution ci-dessus.
  • utiliser un plugin Docker volume qui supporte un service externe/tiers
    • Les plugins Docker volume permettent à votre source de données de venir de n'importe où - NFS, AWS (S3, EFS, et EBS)
    • selon le plugin/service, vous pouvez attacher des conteneurs simples ou multiples à un seul volume.
    • selon le service, les sauvegardes/restaurations peuvent être automatisées pour vous.
    • bien que cela puisse être difficile à faire à la main, certaines solutions d'orchestration - telles que Rancher - l'ont fait cuire dans et simple pour utiliser.
    • convoi est la solution la plus facile pour le faire manuellement.
5
répondu Will Stern 2018-07-25 16:19:52

cela dépend de votre scénario (ce n'est pas vraiment approprié pour un environnement de production), mais voici une façon:

création D'un conteneur MySQL Docker

Cet essentiel, c'est d'utiliser un répertoire sur votre hôte pour la persistance des données.

4
répondu ben schwartz 2018-07-25 04:49:46

j'ai récemment écrit au sujet d'une solution potentielle et une application démontrant la technique. Je trouve que c'est assez efficace pendant le développement et la production. J'espère que ça aidera ou suscitera des idées.

Repo: https://github.com/LevInteractive/docker-nodejs-example

Article: http://lev-interactive.com/2015/03/30/docker-load-balanced-mongodb-persistence /

2
répondu slth 2015-04-02 12:29:18

j'utilise juste un répertoire prédéfini sur l'hôte pour persister les données pour PostgreSQL. De plus, il est possible de migrer facilement les installations PostgreSQL existantes vers les conteneurs Docker: https://crondev.com/persistent-postgresql-inside-docker/

1
répondu Alen Komljen 2018-07-25 16:04:25

ma solution est d'obtenir l'utilisation de la nouvelle docker cp , qui est maintenant en mesure de copier des données à partir de conteneurs, peu importe si elle est en cours d'exécution ou non et partager un volume hôte à l'endroit exact où l'application de base de données est en train de créer ses fichiers de base de données à l'intérieur du conteneur. Cette solution double fonctionne sans conteneur de données, directement à partir du conteneur original de la base de données.

ainsi mon script d'initialisation de systemd prend le travail de sauvegarder la base de données dans un archives sur l'ordinateur hôte. J'ai placé un timestamp dans le nom de fichier pour ne jamais réécrire un fichier.

C'est de le faire sur la ExecStartPre:

ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'

et il fait la même chose sur ExecStopPost aussi:

ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'

Plus j'ai exposé un dossier de l'hôte comme un volume au même endroit exact où la base de données est stockée:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

cela fonctionne très bien sur ma VM (je construis une pile de Lep pour moi-même): https://github.com/DJviolin/LEMP

mais je ne sais pas si c'est une solution" pare-balles " quand votre vie en dépend réellement (par exemple, boutique en ligne avec des transactions en quelques millisecondes)?

à 20 min 20 s de cette vidéo officielle de Docker, le présentateur fait la même chose avec la base de données:

démarrer avec le Panneau

" pour la base de données nous avons un volume, de sorte que nous pouvons nous assurer que, comme la base de données monte et descend, nous ne perdons pas de données, lorsque le conteneur de la base de données s'est arrêté."

0
répondu Lanti 2018-07-25 15:56:46

utiliser revendication de Volume persistante (PVC) de Kubernetes, qui est un Docker container outil de gestion et de planification:

"Volumes Persistants

l'utilisation de Kubernetes dans ce but présente les avantages suivants:

  • vous pouvez utiliser n'importe quel stockage comme NFS ou autre stockage et même lorsque le noeud est en panne, le stockage n'a pas besoin d'être.
  • de plus les données contenues dans ces volumes peuvent être configurées pour être conservées même après la destruction du conteneur lui - même-de sorte qu'elles puissent être récupérées, si nécessaire, par un autre conteneur.
0
répondu Santanu Dey 2018-07-25 16:12:07