web-dev-qa-db-fra.com

Configurer MySQL et importer un dump dans Dockerfile

J'essaie de configurer un fichier Dockerfile pour mon projet LAMP, mais je rencontre quelques problèmes lors du démarrage de MySQL. J'ai les lignes suivantes sur mon Dockerfile:

VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql

Mais je continue à avoir cette erreur:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

Des idées sur la configuration de la création de la base de données et de l’importation de dump lors de la construction de Dockerfile?

113
vinnylinux

Chaque instruction RUN dans un Dockerfile est exécutée dans une couche différente (comme expliqué dans documentation de RUN ).

Dans votre Dockerfile, vous avez trois instructions RUN. Le problème est que le serveur MySQL n'est démarré que dans le premier. Dans les autres, aucun MySQL n'est en cours d'exécution, c'est pourquoi vous obtenez une erreur de connexion avec le client mysql.

Pour résoudre ce problème, vous avez 2 solutions.

Solution 1: utilisez une ligne RUN

RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && \
  sleep 5 && \
  mysql -u root -e "CREATE DATABASE mydb" && \
  mysql -u root mydb < /tmp/dump.sql

Solution 2: utilisez un script

Créez un script exécutable init_db.sh:

#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql

Ajoutez ces lignes à votre Dockerfile:

ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh
109
Kuhess

La dernière version de la version officielle image mysql docker vous permet d'importer des données au démarrage. Voici mon docker-compose.yml

_data:
  build: docker/data/.
mysql:
  image: mysql
  ports:
    - "3307:3306"
  environment:
    MYSQL_ROOT_PASSWORD: 1234
  volumes:
    - ./docker/data:/docker-entrypoint-initdb.d
  volumes_from:
    - data
_

Ici, j'ai mon data-dump.sql sous _docker/data_ qui est relatif au dossier à partir duquel docker-compose est en cours d'exécution. Je monte ce fichier SQL dans ce répertoire _/docker-entrypoint-initdb.d_ sur le conteneur.

Si cela vous intéresse de voir comment cela fonctionne, regardez leur docker-entrypoint.sh dans GitHub. Ils ont ajouté ce bloc pour permettre l'importation de données

_    echo
    for f in /docker-entrypoint-initdb.d/*; do
        case "$f" in
            *.sh)  echo "$0: running $f"; . "$f" ;;
            *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
            *)     echo "$0: ignoring $f" ;;
        esac
        echo
    done
_

Remarque supplémentaire, si vous souhaitez que les données soient conservées même après que le conteneur mysql soit arrêté et supprimé, vous devez disposer d'un conteneur de données distinct, comme vous le voyez dans le fichier docker-compose.yml. Le contenu du conteneur de données Dockerfile est très simple.

_FROM n3ziniuka5/ubuntu-Oracle-jdk:14.04-JDK8

VOLUME /var/lib/mysql

CMD ["true"]
_

Le conteneur de données n'a même pas besoin d'être à l'état de démarrage pour la persistance.

151
Rajiv

Ce que j'ai fait est de télécharger mon dump SQL dans un dossier "db-dump" et de le monter:

mysql:
 image: mysql:5.6
 environment:
   MYSQL_ROOT_PASSWORD: pass
 ports:
   - 3306:3306
 volumes:
   - ./db-dump:/docker-entrypoint-initdb.d

Lorsque je lance docker-compose up pour la première fois, le dump est restauré dans la base de données.

33
Petru

J'ai utilisé l'approche docker-entrypoint-initdb.d (Merci à @Kuhess), mais dans mon cas, je veux créer ma base de données en fonction de certains paramètres que j'ai définis dans le fichier .env.

1) Je définis d'abord le fichier .env dans le répertoire racine de mon projet.

MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306

2) Ensuite, je définis mon fichier docker-compose.yml. J'ai donc utilisé la directive args pour définir mes variables d'environnement et je les ai définies à partir d'un fichier .env

version: '2'
services:
### MySQL Container
    mysql:
        build:
            context: ./mysql
            args:
                - MYSQL_DATABASE=${MYSQL_DATABASE}
                - MYSQL_USER=${MYSQL_USER}
                - MYSQL_PASSWORD=${MYSQL_PASSWORD}
                - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
        ports:
            - "${MYSQL_PORT}:3306"

) Ensuite, je définis un dossier mysql qui inclut un fichier Docker. Donc, le Dockerfile est-ce

FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/

ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD

ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD

ADD data.sql /etc/mysql/data.sql
RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d

EXPOSE 3306

4) J'utilise maintenant mysqldump pour dumper ma base de données et placer le fichier data.sql dans le dossier mysql

mysqldump -h <server name> -u<user> -p <db name> > data.sql

Le fichier est juste un fichier de dump SQL normal mais j'ajoute 2 lignes au début pour que le fichier ressemble à ceci

--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;

-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...

C’est donc que j’ai utilisé la commande "RUN sed -i"/MYSQL_DATABASE/'$ MYSQL_DATABASE "/ g' /etc/mysql/data.sql" pour remplacer l’espace réservé MYSQL_DATABASE avec le nom de mon DB qui Je l'ai mis dans le fichier .env.

|- docker-compose.yml
|- .env
|- mysql
     |- Dockerfile
     |- data.sql

Vous êtes maintenant prêt à construire et à exécuter votre conteneur

9
Saman Shafigh

Voici une version de travail utilisant v3 de docker-compose.yml. La clé est la directive volumes :

mysql:
  image: mysql:5.6
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_USER: theusername
    MYSQL_PASSWORD: thepw
    MYSQL_DATABASE: mydb
  volumes:
    - ./data:/docker-entrypoint-initdb.d

Dans le répertoire où se trouve mon docker-compose.yml, j'ai un répertoire data contenant les fichiers .sql. C'est bien parce que vous pouvez avoir un fichier de vidage .sql par table.

Je lance simplement docker-compose up et je suis prêt à partir. Les données persistent automatiquement entre les arrêts. Si vous souhaitez supprimer les données et "aspirer" de nouveaux fichiers .sql, exécutez docker-compose down puis docker-compose up.

Si quelqu'un sait comment amener le menu fixe mysql à retraiter des fichiers dans /docker-entrypoint-initdb.d sans supprimer le volume, veuillez laisser un commentaire et je mettrai à jour cette réponse.

5
rynop