web-dev-qa-db-fra.com

Docker, comment exécuter un fichier .sql dans une image?

C'est la première fois que je travaille avec Docker et je ne sais pas si je fais bien les choses.

J'ai une Rails applications qui dépend d'une base de données Mysql, j'ai donc configuré la docker-compose.yml fichier comme celui-ci:

db:
  image: library/mysql:5.6
  environment:
    MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
  expose:
    - "3306"
  ports:
    - "3306:3306"

Rails-app:
  build: .
  dockerfile: Dockerfile
  environment:
    Rails_ENV: development
  links:
    - db
  volumes:
    - ".:/home/app"
  volumes_from:
    - bundle

  ... omitted lines ...

Ensuite, si je lance ce qui suit:

$ docker-compose run db mysql --Host=$DOCKER_LOCALHOST --port=3306 --protocol=tcp -u root < shared/create_common_tables.sql

Je reçois cette erreur:

ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.99.100' (111)

Cela semble normal, car je soupçonne que je dois build avant un conteneur qui relie à db.

Je le sais parce que si je lance ceci dans cet ordre:

$ docker-compose build Rails-app
$ docker-compose run -e Rails_ENV=development Rails-app bundle
$ docker-compose run -e Rails_ENV=development Rails-app bundle exec rake db:create
$ docker-compose run db mysql --Host=$DOCKER_LOCALHOST --port=3306 --protocol=tcp -u root < shared/create_common_tables.sql

Ça fonctionne bien.

Mais, comment puis-je faire pour exécuter ce SQL avant de créer un conteneur?

20
Fran Martinez

Vous pouvez charger le fichier sql pendant la phase build de l'image. Pour ce faire, vous créez un Dockerfile pour le service db qui ressemblera à ceci:

FROM mysql:5.6
COPY setup.sh /mysql/setup.sh
COPY setup.sql /mysql/setup.sql
RUN /mysql/setup.sh

setup.sh ressemble à ceci:

#!/bin/bash
set -e
service mysql start
mysql < /mysql/setup.sql
service mysql stop

Et dans votre docker-compose.yml, Vous changeriez image en build: ./db Ou le chemin où vous placez vos fichiers.

Maintenant, cela fonctionne si vous avez tout votre sql dans un fichier brut .sql, Mais ce ne sera pas le cas si vous utilisez Rails ou un framework similaire où le sql est réellement stocké dans le code. Cela vous laisse deux options.

  1. Au lieu d'utiliser FROM mysql:5.6, Vous pouvez utiliser FROM your_app_image_that_has_the_code_in_it Et apt-get install mysql .... Cela vous laisse une image plus grande qui contient à la fois mysql et votre application, vous permettant d'exécuter les commandes Ruby ci-dessus. Vous remplaceriez le mysql < /mysql/setup/sql Par le Rails-app bundle exec rake db:create Vous devez également fournir une configuration d'application qui frappe une base de données sur localhost:3306 au lieu de db:3306

  2. Mon option préférée est de créer un script qui exporte le sql dans un fichier .sql, Que vous pouvez ensuite utiliser pour construire votre conteneur de base de données. C'est un peu plus de travail, mais c'est beaucoup plus agréable. Cela signifie qu'au lieu d'exécuter Rails-app bundle exec rake db:create, Il vous suffit d'exécuter le script pour charger une base de données.

Un tel script ressemblerait à ceci:

#!/bin/bash
set -e
docker-compose build Rails-app
docker run -d --name mysql_empty mysql:5.6
docker run --link mysql_empty:db -v $PWD:/output project_Rails-app export.sh

export.sh ressemble à ceci:

#!/bin/bash
set -e
Rails_ENV=development
Rails-app bundle exec rake db:create
mysqldump > /output/setup.sql

Vous pouvez également remplacer le script docker run Par un deuxième fichier de composition si vous le souhaitez.

15
dnephin