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?
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.
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
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
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.
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.
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
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.