web-dev-qa-db-fra.com

Les scripts MySQL dans docker-entrypoint-initdb ne sont pas exécutés

J'essaie de créer plusieurs bases de données au démarrage d'un conteneur MySQL. Selon https://github.com/docker-library/mysql/pull/18 , je peux monter ou copier mes scripts dans le /docker-entrypoint-initdb.d de l'image et ils seront exécutés automatiquement au démarrage.

Cependant mes scripts ne sont pas du tout exécutés. On dirait que le docker-entrypoint.sh ne voit pas les fichiers dans le répertoire /docker-entrypoint-initdb.d.

C'est mon Dockerfile:

FROM mysql
ADD script.sql /docker-entrypoint-initdb.d/script.sql
RUN chmod -R 775 /docker-entrypoint-initdb.d

ENV MYSQL_ROOT_PASSWORD mypass

C'est mon script.sql:

CREATE DATABASE mydb;
CREATE DATABASE mydb2;

Je construis et exécute le conteneur:

$ docker build -t mysql .
$ docker run -v data_volume:/var/lib/mysql --name somedb -d mysql

Lorsque j'accède au conteneur dans tty, je peux voir que le script.sql est dans le /docker-entrypoint-initdb.d mais n'est pas exécuté.

J'ai vu la sortie docker logs -f somedb mais il n'y a pas d'erreur.

J'ai essayé avec le fichier .sh, j'ai aussi essayé avec Maria-db, le résultat est le même.

Quel pourrait être le problème?

7
Canis Majoris

Veuillez vider data_volume avant d'exécuter votre conteneur. Et vos fichiers SQL seront exécutés à coup sûr.

Problèmes ici:

Dans docker-entrypoint.sh, cochez la première exécution en utilisant le répertoire exist de mysql dans/var/lib/mysql

if [ ! -d "$DATADIR/mysql" ]; then
    //Some other logic here

    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 ;;
            *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
            *)        echo "$0: ignoring $f" ;;
        esac
        echo
    done 

Vous pouvez obtenir plus de détails sur Source Dockerfile

7
Ricky

J'ai donc eu le même problème pendant des heures, puis j'ai décidé de me pencher sur docker-entrypoint.sh. Il s'avère que le script vérifie $ DATADIR/mysql, type/var/lib/mysql, et ignore le reste du code si le datadir existe, incl. docker-entrypoint-initdb.d

Donc, ce que j’ai fait, c’est de créer un simple fichier init.sh pour supprimer le datadir, puis démarrer le menu fixe.

docker-compose.yml: volumes: - ./docker/mysql/scripts:/docker-entrypoint-initdb.d - ./mysql_data:/var/lib/mysql

init.sh: #!/bin/bash rm -rf mysql_data docker-compose up --force-recreate Et bien sûr, ajoutez -d à docker-composer une fois que je vois que cela fonctionne comme prévu.

Brève description
J'ai exactement le même problème, mais avec une image mariadb (qui semble avoir exactement le même docker-entrypoint.sh que celle de mysql), et j'aimerais contribuer à ce fil. Espérons que si nous nous plaignons beaucoup à propos de ce problème, nous pourrons le réparer :) 

Le script .sql contenu dans le dossier "docker-entrypoint-initdb.d" est ignoré lorsque j'exécute docker-compose.ymlsur mon environnement de production ( Linux), alors que exactement le même fichier fonctionne parfaitement sur mon environnement de développement (Windows 7)

Cela ne me permet pas de construire la structure de la base de données (le fichier .sql contient toutes les instructions CREATE TABLE ...), donc c'est un élément majeur pour moi

Description détaillée
J'ai essayé les solutions suivantes:

  • Changer EOL pour le .sql de CRLF à LF;
  • Différents paramètres de chmod pour "docker-entrypoint-initdb.d}" (et les scripts contenus);
  • Saisie du conteneur avec "docker exec" (le dossier et les scripts sont accessibles depuis le conteneur comme prévu);
  • Ajouter un fichier * .sh à "docker-entrypoint-initdb.d" (il sera ignoré exactement comme le .sql);

Pas de succès jusqu'à présent. Vérification des journaux avec:

$ docker logs someappname_db >& logs_db.txt

montre que le bloc de code suivant provenant de docker-entrypoint.sh n'est pas appelé du tout dans l'environnement Linux, exactement comme @anteverse le dit:

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 ;;
       *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
       *)        echo "$0: ignoring $f" ;;
   esac
   echo
done

En entrant dans le conteneur avec "docker exec", je vois les autorisations suivantes: 

Sous Linux:

root@deda78e393f9:/# ls -l
total 72
drwxr-xr-x    2 root root 4096 Mar 19 19:53 bin
drwxr-xr-x    2 root root 4096 Nov 19 16:32 boot
drwxr-xr-x    5 root root  340 Apr 29 15:53 dev
**drwxrwxrwx+   2 root root 4096 Apr 29 11:30 docker-entrypoint-initdb.d**
lrwxrwxrwx    1 root root   34 Mar 14 06:26 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
...

Sous Windows 7:

root@a3ff19060712:/# ls -l
total 64
drwxr-xr-x   2 root root  4096 Feb 17 09:07 bin
drwxr-xr-x   2 root root  4096 Nov 19 16:32 boot
drwxr-xr-x   5 root root   340 Apr 29 16:04 dev
**drwxrwxrwx   1 1000 staff    0 Apr 28 18:13 docker-entrypoint-initdb.d**
lrwxrwxrwx   1 root root    34 Feb 17 09:08 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
...

Pourrait-il être lié à l'UID: GID? Devrait-il y avoir 1000 personnes sur Linux?

L'utilisateur sur mon hôte Linux s'appelle 'admin', peut-être peut-être une racine incompatible (sur le conteneur): admin (sur l'hôte)?

Caractéristiques
Environnement de développement: Windows 7, Docker 18.02.0-CE
Environnement de production: version non spécifiée de Linux (QNAP TS-253A), Docker 17.07.0-CE

[/share/Container/] # uname -or
4.2.8 GNU/Linux

[/share/Container/] # cat /etc/issue
Welcome to TS-253A, QNAP Systems, Inc.

[/share/Container/] # cat /etc/os-release
NAME="QTS"
VERSION="4.3.4 (20180215)"
ID=qts
PRETTY_NAME="QTS 4.3.4 (20180215)"
VERSION_ID="4.3.4"

docker-compose.yml

version: '3'
services:

  db:
    container_name: someappname_db
    image: mariadb:latest
    restart: on-failure:3
    environment: 
      - MYSQL_DATABASE=someappname
      - MYSQL_ROOT_PASSWORD=someappname
      - MYSQL_USER=someappname
      - MYSQL_PASSWORD=someappname
      - MYSQL_ROOT_Host=%
      - TZ=Europe/Stockholm
    ports:
      - 3306:3306  
    volumes:
      - dbdata:/var/lib/mysql      
      - /share/Container/someappname/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
    networks:
      - net
    command: ["mysqld", "--user=mysql", "--lower_case_table_names=1"]

    # other services

volumes:
  dbdata:

networks:
  net:

Commandes:
Je nettoie toujours le volume avant de recomposer le conteneur:

$ cd /share/Containers/someappname
$ docker stop $(docker ps -a -q --filter="name=someappname") && docker rm $(docker ps -a -q  --filter="name=someappname") && docker volume rm someappname_dbdata
$ docker-compose -f someappnameprod-docker-compose.yml up -d db

Merci pour ton aide!

2
numbworks

Avez-vous déjà résolu le problème?

Une solution simple consiste à utiliser un chemin absolu lors de la lecture de fichiers dans /docker-entrypoint-initdb.d/

J'ai fait mon test en utilisant la configuration par défaut de: https://github.com/docker-library/mysql/blob/master/5.7/Dockerfile#L70

Le fichier docker-entrypoint.sh est d’abord déplacé vers/usr/local/bin avant son exécution. 

Ensuite, il faut lire les fichiers dans /docker-entrypoint-initdb.d/, mais les suivants:

for f in /docker-entrypoint-initdb.d/*; do

ne semble rien trouver.

Si vous le remplacez par:

for f in /usr/local/bin/docker-entrypoint-initdb.d/*; do

puis assurez-vous que le dossier est rempli par la commande Dockerfile:

COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

COPY docker-entrypoint-initdb.d/ /usr/local/bin/docker-entrypoint-initdb.d/
RUN chmod -R +x /usr/local/bin/docker-entrypoint-initdb.d

À partir de là, créez une instruction de test dans /docker-entrypoint-initdb.d/test.sql

CREATE DATABASE `test`;

Enfin, construisez et exécutez l'image et vous devriez voir votre base de données créée.

1
anteverse

J'ai eu le même problème. Je l'ai résolu en changeant le propriétaire du répertoire avant de lancer le script de point d'entrée. Exemple de fichier Docker:

FROM mysql:5.7.17
ADD scripts/init.sql /docker-entrypoint-initdb.d/

RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/

CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
0
user1291806

pas vraiment une réponse à ce comportement mais je le fais habituellement comme ça:

RUN mkdir -p /docker-entrypoint-initdb.d && mv myScript.sql /docker-entrypoint-initdb.d/myScript.sql

ne pensez pas qu'il y a quelque chose qui cloche dans votre code mais qui sait. Je suppose que vous avez coché 775 est le bon propriétaire? btw im using FROM mysql: 5

0
Zeromus