Comment puis-je initialiser une base de données MySQL avec schema dans un conteneur Docker?

j'essaie de créer un conteneur avec une base de données MySQL et d'ajouter un schéma à ces bases de données.

mon fichier actuel est:

FROM mysql
MAINTAINER  (me) <email>

# Copy the database schema to the /data directory
COPY files/epcis_schema.sql /data/epcis_schema.sql

# Change the working directory
WORKDIR data

CMD mysql -u $MYSQL_USER -p $MYSQL_PASSWORD $MYSQL_DATABASE < epcis_schema.sql

pour créer le conteneur, je suis la documentation fournie sur Docker et j'exécute cette commande:

docker run --name ${CONTAINER_NAME} -e MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} -e MYSQL_USER=${DB_USER} -e MYSQL_PASSWORD=${DB_USER_PASSWORD} -e MYSQL_DATABASE=${DB_NAME} -d mvpgomes/epcisdb

mais quand j'exécute cette commande le conteneur n'est pas créé et dans le statut du conteneur il est possible de voir que le CMD n'a pas été exécuté avec succès, en fait seule la commande mysql est exécutée.

de toute façon, il est un moyen d'initialiser la base de données avec le schéma ou dois-je effectuer ces opérations manuellement?

101
demandé sur Martin Thoma 2015-03-19 16:04:44

10 réponses

je suis désolé pour cette très longue réponse, mais, vous avez un peu de chemin à faire pour arriver là où vous voulez. Je dirai que normalement vous ne mettriez pas le stockage de la base de données dans le même conteneur que la base de données elle-même, vous monteriez soit un volume hôte de sorte que les données persistent sur l'hôte docker, ou, peut-être un conteneur pourrait être utilisé pour contenir les données (/var/lib/mysql). Aussi, je suis nouveau à mysql, donc, cela pourrait ne pas être super efficace. Qui a dit...

je pense il y a peut être quelques questions ici. Le fichier Dockerfile est utilisé pour créer une image. Vous devez exécuter l'étape de génération. Au minimum, à partir du répertoire qui contient le fichier Dockerfile vous feriez quelque chose comme:

docker build .

le fichier Dockerfile décrit l'image à créer. Je ne sais pas grand chose sur mysql (je suis un fan de postgres), mais, j'ai fait une recherche dans les interwebs pour 'comment initialiser un conteneur de docker mysql'. J'ai d'abord créé un nouveau répertoire de travail, je Je l'ai appelé mdir, puis j'ai créé un répertoire de fichiers que j'ai déposé dans epcis_schema.fichier sql qui crée une base de données et une table unique:

create database test;
use test;

CREATE TABLE testtab
(
id INTEGER AUTO_INCREMENT,
name TEXT,
PRIMARY KEY (id)
) COMMENT='this is my test table';

puis j'ai créé un script appelé init_db dans le répertoire des fichiers:

#!/bin/bash

# Initialize MySQL database.
# ADD this file into the container via Dockerfile.
# Assuming you specify a VOLUME ["/var/lib/mysql"] or `-v /var/lib/mysql` on the `docker run` command…
# Once built, do e.g. `docker run your_image /path/to/docker-mysql-initialize.sh`
# Again, make sure MySQL is persisting data outside the container for this to have any effect.

set -e
set -x

mysql_install_db

# Start the MySQL daemon in the background.
/usr/sbin/mysqld &
mysql_pid=$!

until mysqladmin ping >/dev/null 2>&1; do
  echo -n "."; sleep 0.2
done

# Permit root login without password from outside container.
mysql -e "GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '' WITH GRANT OPTION"

# create the default database from the ADDed file.
mysql < /tmp/epcis_schema.sql

# Tell the MySQL daemon to shutdown.
mysqladmin shutdown

# Wait for the MySQL daemon to exit.
wait $mysql_pid

# create a tar file with the database as it currently exists
tar czvf default_mysql.tar.gz /var/lib/mysql

# the tarfile contains the initialized state of the database.
# when the container is started, if the database is empty (/var/lib/mysql)
# then it is unpacked from default_mysql.tar.gz from
# the ENTRYPOINT /tmp/run_db script

(la plupart de ce script a été supprimé d'ici: https://gist.github.com/pda/9697520 )

Voici les fichiers / script run_db que j'ai créé:

# start db

set -e
set -x

# first, if the /var/lib/mysql directory is empty, unpack it from our predefined db
[ "$(ls -A /var/lib/mysql)" ] && echo "Running with existing database in /var/lib/mysql" || ( echo 'Populate initial db'; tar xpzvf default_mysql.tar.gz )

/usr/sbin/mysqld

enfin, le fichier Dockerfile pour les lier tous:

FROM mysql
MAINTAINER  (me) <email>

# Copy the database schema to the /data directory
ADD files/run_db files/init_db files/epcis_schema.sql /tmp/

# init_db will create the default
# database from epcis_schema.sql, then
# stop mysqld, and finally copy the /var/lib/mysql directory
# to default_mysql_db.tar.gz
RUN /tmp/init_db

# run_db starts mysqld, but first it checks
# to see if the /var/lib/mysql directory is empty, if
# it is it is seeded with default_mysql_db.tar.gz before
# the mysql is fired up

ENTRYPOINT "/tmp/run_db"

donc, j'ai cd'ed à mon répertoire mdir (qui a le fichier Dock avec le répertoire des fichiers). J'exécute alors la commande:

docker build --no-cache .

vous devriez voir la sortie comme ceci:

Sending build context to Docker daemon 7.168 kB
Sending build context to Docker daemon 
Step 0 : FROM mysql
 ---> 461d07d927e6
Step 1 : MAINTAINER (me) <email>
 ---> Running in 963e8de55299
 ---> 2fd67c825c34
Removing intermediate container 963e8de55299
Step 2 : ADD files/run_db files/init_db files/epcis_schema.sql /tmp/
 ---> 81871189374b
Removing intermediate container 3221afd8695a
Step 3 : RUN /tmp/init_db
 ---> Running in 8dbdf74b2a79
+ mysql_install_db
2015-03-19 16:40:39 12 [Note] InnoDB: Using atomics to ref count buffer pool pages
...
/var/lib/mysql/ib_logfile0
 ---> 885ec2f1a7d5
Removing intermediate container 8dbdf74b2a79
Step 4 : ENTRYPOINT "/tmp/run_db"
 ---> Running in 717ed52ba665
 ---> 7f6d5215fe8d
Removing intermediate container 717ed52ba665
Successfully built 7f6d5215fe8d

vous avez maintenant une image '7f6d5215fe8d'. Je pourrais lancer cette image:

docker run -d 7f6d5215fe8d

et l'image démarre, je vois une chaîne de caractères d'instance:

4b377ac7397ff5880bc9218abe6d7eadd49505d50efb5063d6fab796ee157bd3

je pourrais alors "l'arrêter" et le redémarrer.

docker stop 4b377
docker start 4b377

si vous regardez les logs, la première ligne contiendra:

docker logs 4b377

Populate initial db
var/lib/mysql/
...

puis, à la fin des logs:

Running with existing database in /var/lib/mysql

ce sont les messages du script /tmp / run_db, le premier indique que la base de données a été déballée de la version sauvée (initiale), le second indique que la base de données était déjà là, donc la copie existante a été utilisée.

voici un ls-lR de la structure de répertoire que je décris ci-dessus. Notez que init_db et run_db sont des scripts avec le bit d'exécution défini:

gregs-air:~ gfausak$ ls -Rl mdir
total 8
-rw-r--r--  1 gfausak  wheel  534 Mar 19 11:13 Dockerfile
drwxr-xr-x  5 gfausak  staff  170 Mar 19 11:24 files

mdir/files:
total 24
-rw-r--r--  1 gfausak  staff   126 Mar 19 11:14 epcis_schema.sql
-rwxr-xr-x  1 gfausak  staff  1226 Mar 19 11:16 init_db
-rwxr-xr-x  1 gfausak  staff   284 Mar 19 11:23 run_db
67
répondu Greg 2016-12-01 22:11:36

j'ai eu ce même problème où j'ai voulu initialiser le schéma de mon instance de MySQL Docker, mais j'ai eu des difficultés à obtenir ce fonctionnement après avoir fait quelques recherches sur Google et avoir suivi d'autres exemples. Voici comment je l'ai résolu.

1) Dump MySQL schéma d'un fichier.

mysqldump -h <your_mysql_host> -u <user_name> -p --no-data <schema_name> > schema.sql

2) Utilisez la commande ADD pour ajouter votre fichier schema au répertoire /docker-entrypoint-initdb.d dans le conteneur Docker. Le fichier docker-entrypoint.sh exécutera tous les fichiers de cette répertoire se terminant par ".sql" contre la base de données MySQL.

Dockerfile:

FROM mysql:5.7.15

MAINTAINER me

ENV MYSQL_DATABASE=<schema_name> \
    MYSQL_ROOT_PASSWORD=<password>

ADD schema.sql /docker-entrypoint-initdb.d

EXPOSE 3306

3) Démarrer L'instance MySQL du Docker.

docker-compose build
docker-compose up

merci à mise en place MySQL et l'importation dump dans Dockerfile pour m'avoir inclus dans le docker-entrypoint.sh et le fait qu'il exécute des scripts SQL et shell!

67
répondu Brett Cooper 2017-05-23 12:34:50

J'ai essayé la réponse de Greg avec zéro succès, j'ai dû faire quelque chose de mal puisque ma base de données n'avait pas de données après toutes les étapes: j'utilisais la dernière image de MariaDB, juste au cas où.

puis j'ai décidé de lire le point d'entrée pour le image MariaDB , et utilisé pour générer un simple docker-composer fichier:

database:
  image: mariadb
  ports:
     - 3306:3306
  expose:
     - 3306
  volumes:
     - ./docker/mariadb/data:/var/lib/mysql:rw
     - ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
  environment:
     MYSQL_ALLOW_EMPTY_PASSWORD: "yes"

maintenant je suis capable de persister mes données et générer une base de données avec mon propre schéma!

19
répondu mrArias 2016-04-04 16:10:40

une autre manière basée sur une fusion de réponses Server ici avant:

docker-composer file :

version: "3"
services:
    db:
      container_name: db
      image: mysql
      ports:
       - "3306:3306"  
      environment:
         - MYSQL_ROOT_PASSWORD=mysql
         - MYSQL_DATABASE=db

      volumes:
         - /home/user/db/mysql/data:/var/lib/mysql
         - /home/user/db/mysql/init:/docker-entrypoint-initdb.d/:ro

/home/user .. est un dossier partagé sur l'hôte

et dans le dossier /home/user/db/mysql/init .. il suffit de déposer un fichier sql, avec n'importe quel nom, par exemple init.sql contenant:

CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%' IDENTIFIED BY 'mysql';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost' IDENTIFIED BY 'mysql';
USE mydb
CREATE TABLE CONTACTS (
    [ ... ]
);
INSERT INTO CONTACTS VALUES ...
[ ... ]

selon la documentation officielle mysql , vous pouvez mettre plus qu'un fichier sql dans le docker-entrypoint-initdb.d , ils sont exécutés dans l'ordre alphabétique

18
répondu phico 2017-06-01 13:16:21

After Aug. 4, 2015, Si vous utilisez l'image officielle de mysql, vous pouvez simplement ajouter/copier un fichier dans le fichier /docker-entrypoint-initdb.d / directory et il s'exécutera avec le conteneur est initialisé. Voir github: https://github.com/docker-library/mysql/commit/14f165596ea8808dfeb2131f092aabe61c967225 si vous voulez l'implémenter sur d'autres images de conteneur

14
répondu JDWatkins 2016-08-12 14:40:11

la solution la plus simple est d'utiliser tutum / mysql

Etape 1

docker pull tutum/mysql:5.5

Step2

docker run -d -p 3306:3306 -v /tmp:/tmp  -e STARTUP_SQL="/tmp/to_be_imported.mysql" tutum/mysql:5.5

Etape 3

Obtenir au-dessus de CONTAINER_ID puis exécuter la commande docker logs pour voir le mot de passe généré de l'information.

docker logs #<CONTAINER_ID>
10
répondu mainframer 2015-12-20 04:22:35

l'autre manière simple, utiliser docker-composer avec les lignes suivantes:

mysql:
  from: mysql:5.7
  volumes:
    - ./database:/tmp/database
  command: mysqld --init-file="/tmp/database/install_db.sql"

mettez votre schéma de base de données dans le ./base de données/install_db.SQL. Chaque fois que vous construisez votre conteneur, install_db.sql exécuté.

5
répondu Balázs Zámbó 2017-01-26 10:41:21

pour ceux qui ne veulent pas créer un script point d'entrée comme moi, vous pouvez démarrer mysqld à la compilation et ensuite exécuter les commandes mysql dans votre fichier Dockerfile comme suit:

RUN mysqld_safe & until mysqladmin ping; do sleep 1; done && \
    mysql -uroot -e "CREATE DATABASE somedb;" && \
    mysql -uroot -e "CREATE USER 'someuser'@'localhost' IDENTIFIED BY 'somepassword';" && \
    mysql -uroot -e "GRANT ALL PRIVILEGES ON somedb.* TO 'someuser'@'localhost';"

la clé ici est d'envoyer mysqld_safe en arrière-plan avec le simple signe & .

3
répondu roothahn 2018-02-06 16:53:21

après pour lutter un peu avec cela, jetez un oeil au fichier Dockerfile en utilisant des volumes nommés (db-data). Il est important de déclarer un plus à la dernière partie, où j'ai mentionné que le volume est [external]

tout a bien fonctionné!

version: "3"

services:

  database:
    image: mysql:5.7
    container_name: mysql
    ports:
      - "3306:3306"
    volumes:
      - db-data:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_DATABASE=sample
      - MYSQL_ROOT_PASSWORD=root

volumes:
  db-data:
    external: true
1
répondu allysson vieira 2017-05-02 09:38:13

ci-dessous est le fichier Dockerfile que j'ai utilisé avec succès pour installer xampp, créer une MariaDB avec scheme et pré-rempli avec les informations utilisées sur le serveur local(usrs,pics commandes,etc..)

FROM ubuntu:14.04

COPY Ecommerce.sql /root

RUN apt-get update \
 && apt-get install wget -yq \
 && apt-get install nano \
 && wget https://www.apachefriends.org/xampp-files/7.1.11/xampp-linux-x64-7.1.11-0-installer.run \
 && mv xampp-linux-x64-7.1.11-0-installer.run /opt/ \
 && cd /opt/ \
 && chmod +x xampp-linux-x64-7.1.11-0-installer.run \
 && printf 'y\n\y\n\r\n\y\n\r\n' | ./xampp-linux-x64-7.1.11-0-installer.run \
 && cd /opt/lampp/bin \
 && /opt/lampp/lampp start \
 && sleep 5s \

 && ./mysql -uroot -e "CREATE DATABASE Ecommerce" \
 && ./mysql -uroot -D Ecommerce < /root/Ecommerce.sql \
 && cd / \
 && /opt/lampp/lampp reload \
 && mkdir opt/lampp/htdocs/Ecommerce

COPY /Ecommerce /opt/lampp/htdocs/Ecommerce

EXPOSE 80
1
répondu Paddy Popeye 2017-11-21 00:50:30