Docker-Compose données persistantes MySQL

156

Je n'arrive pas à faire en sorte que les données MySQL persistent si je cours $ docker-compose downavec ce qui suit.yml

version: '2'
services:
  # other services

  data:
    container_name: flask_data
    image: mysql:latest
    volumes:
      - /var/lib/mysql
    command: "true"

  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes_from:
      - data
    ports:
      - "3306:3306"

Ma compréhension est que dans mon dataconteneur, l'utilisation de volumes: - /var/lib/mysqlmappe vers mon répertoire de machines locales où mysql stocke les données dans le conteneur et à cause de ce mappage, les données devraient persister même si les conteneurs sont détruits. Et le mysqlconteneur n'est qu'une interface client dans la base de données et peut voir le répertoire local en raison devolumes_from: - data

J'ai tenté cette réponse et cela n'a pas fonctionné. Problème de données persistantes Docker-Compose

ÉDITER

J'ai changé mon .ymlcomme indiqué ci-dessous et créé un répertoire, ./datamais maintenant, lorsque j'exécute docker-compose up --buildle mysqlconteneur, ne démarre pas, une erreur en disant

  data:
    container_name: flask_data
    image: mysql:latest
    volumes:
      - ./data:/var/lib/mysql
    command: "true"

  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes_from:
      - data
    ports:
      - "3306:3306"


flask_mysql | mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied)
flask_mysql | 2016-08-26T22:29:21.182144Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
flask_mysql | 2016-08-26T22:29:21.185392Z 0 [ERROR] --initialize specified but the data directory exists and is not writable. Aborting.
Adam
la source

Réponses:

223

Le conteneur de données est une solution de contournement superflue. Les volumes de données feraient l'affaire pour vous. Modifiez votre docker-compose.yml:

version: '2'
services:
  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes:
      - my-datavolume:/var/lib/mysql
volumes:
  my-datavolume:

Docker créera le volume pour vous dans le /var/lib/docker/volumesdossier. Ce volume persiste tant que vous ne tapez pasdocker-compose down -v

Oh mec
la source
18
À partir de MySQL 5.7.6, il y aura (encore) des problèmes de permission avec l' mysqlimage Docker. Vous pouvez à la place utiliser l' mariadbimage Docker, qui fonctionne parfaitement avec les volumes Docker.
Peterino
Cette solution a fonctionné pour moi. Quelques remarques / précisions annexes: 1. lorsque vous utilisez la configuration ci-dessus dans docker-compose.yml et que vous déployez votre pile de services en utilisant "docker stack deploy -c docker-compose.yml mystack", il n'est pas nécessaire de créer le volume manuellement, il sera créé automatiquement comme / var / lib / docker / volumes / mystack_my-datavolume pour vous (notez qu'il ajoute «mystack_» au nom du volume). 2. Je n'ai pas eu à modifier les autorisations sur mon répertoire. Même si j'ai des fichiers appartenant à mysql: root dans mon conteneur, ils ont été créés en tant que 27: root sur mon hôte Docker sans problème.
Joey Cote
10
Pourquoi voulez-vous le stocker au var/lib/docker/volumeslieu d'avoir un répertoire dans votre dossier de projet comme data/mysql?
The Godfather
@TheGodfather Je pense que si vous ne voulez pas déployer des données MySQL sur votre machine de production; sinon, c'est une très bonne idée de garder tout ensemble.
Duncan
1
@louhow je pense parce que je me sens plus confiant lorsque toutes les parties de mon application et de mes données sont stockées ensemble, et que je n'ai aucune dépendance sur un volume de quelque part
The Godfather
53

Il existe 3 façons:

Première voie

Vous devez spécifier le répertoire pour stocker les données mysql sur votre machine hôte . Vous pouvez ensuite supprimer le conteneur de données. Vos données mysql seront enregistrées sur votre système de fichiers local.

La définition du conteneur Mysql doit ressembler à ceci:

mysql:
  container_name: flask_mysql
  restart: always
  image: mysql:latest
  environment:
    MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
    MYSQL_USER: 'test'
    MYSQL_PASS: 'pass'
volumes:
 - /opt/mysql_data:/var/lib/mysql
ports:
  - "3306:3306"

Deuxième voie

Serait de valider le conteneur de données avant de taper docker-compose down:

docker commit my_data_container
docker-compose down

Troisième voie

Vous pouvez également utiliser à la docker-compose stopplace de docker-compose down(alors vous n'avez pas besoin de valider le conteneur)

Boukharov Sergey
la source
Ne puis-je pas juste volumes: - /var/lib/mysqlparce qu'il mappe HOST:CONTAINERet si vous ne spécifiez pas avec deux-points, il mappe le même répertoire?
Adam
Ne pas. malheureusement, dans ce cas, docker mappe ce répertoire de conteneur vers un dossier hôte aléatoire comme/var/lib/docker/volumes/ec3c543bc92f114c2c568733541e89381881e5a62996d7084e07793f86280535
Bukharov Sergey
D'accord, je pensais que volumes: - /var/lib/mysqlc'était équivalent àvolumes: - /var/lib/mysql:/var/lib/mysql
Adam
votre troisième méthode ne fonctionnera pas car docker ne valide pas les données des volumes vers l'image. voir github.com/moby/moby/issues/6999
Ohmen
13

Vous devez créer un volume séparé pour les données mysql.

Cela ressemblera donc à ceci:

volumes_from:
  - data
volumes:
  - ./mysql-data:/var/lib/mysql

Et non, /var/lib/mysqlest un chemin dans votre conteneur mysql et n'a rien à voir avec un chemin sur votre machine hôte. Votre machine hôte peut même ne pas avoir de mysql du tout. Le but est donc de conserver un dossier interne à partir d'un conteneur mysql.

Dmitry Malyshenko
la source
Ne serait-ce pas différent de changer mon volumessous le conteneur de données en ce que vous mettez sous votre volumeset que vous aviez simplement volumes_from: - datapour mysql? Également tenté ceci et thew une nouvelle erreur. Dit que le répertoire existe mais n'est pas accessible en écriture et le mysqlconteneur ne fonctionnera pas.
Adam
Bien sûr, vous devez créer un dossier local avec un chemin ./mysql-data (ou tout ce que vous mettriez avant le point-virgule)
Dmitry Malyshenko
Voir ma modification. Je ne l'ai pas reçu avant de commenter. Mais a créé un répertoire local. Il semble qu'il y ait un problème d'autorisation maintenant.
Adam
ERREUR: Le service "mysql" monte des volumes à partir de "data", qui n'est pas le nom d'un service ou d'un conteneur.
Massimiliano Arione le
10

En fait, c'est le chemin et vous devez mentionner un chemin valide pour que cela fonctionne. Si votre répertoire de données est dans le répertoire actuel, my-datavous devez le mentionner au lieu de cela ./my-data, sinon cela vous donnera cette erreur dans mysqlet mariadbaussi.

volumes:
 ./my-data:/var/lib/mysql
codelearner
la source