initdb - imagen mysql docker
Docker, ¿cómo ejecutar un archivo.sql en una imagen? (1)
Es la primera vez que trabajo con Docker y no estoy seguro de si estoy haciendo las cosas bien.
Tengo una aplicación de rieles que depende de una base de datos Mysql , así que configuré el archivo docker-compose.yml esta manera:
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 ...
Entonces, si corro lo siguiente:
$ docker-compose run db mysql --host=$DOCKER_LOCALHOST --port=3306 --protocol=tcp -u root < shared/create_common_tables.sql
Me sale este error:
ERROR 2003 (HY000): Can''t connect to MySQL server on ''192.168.99.100'' (111)
Esto suena normal, porque sospecho que tengo que build antes de algún contenedor que se vincule a db .
Lo sé porque si ejecuto esto en este orden:
$ 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
Funciona bien.
Pero, ¿cómo puedo hacer para ejecutar este SQL antes de crear cualquier contenedor?
Puede cargar el archivo sql durante la fase de build de la imagen. Para hacer esto, crea un Dockerfile para el servicio db que se verá así:
FROM mysql:5.6
COPY setup.sh /mysql/setup.sh
COPY setup.sql /mysql/setup.sql
RUN /mysql/setup.sh
donde setup.sh ve algo como esto:
#!/bin/bash
set -e
service mysql start
mysql < /mysql/setup.sql
service mysql stop
Y en su docker-compose.yml cambiaría la image para build: ./db o la ruta donde colocó sus archivos.
Ahora esto funciona si tiene todos sus sql en un archivo .sql en bruto, pero no será así si está usando rieles o un marco similar donde el sql se almacena realmente en el código. Esto te deja con dos opciones.
En lugar de usar
FROM mysql:5.6, puede usarFROM your_app_image_that_has_the_code_in_ityapt-get install mysql ...Esto te deja con una imagen más grande que contiene mysql y tu aplicación, lo que te permite ejecutar los comandos de ruby anteriores. Reemplazaríamysql < /mysql/setup/sqlcon elrails-app bundle exec rake db:createlines. También deberías proporcionar una configuración de aplicación que llegue a una base de datos enlocalhost:3306lugar dedb:3306Mi opción preferida es crear un script que exporte el sql a un archivo
.sql, que luego puede usar para construir su contenedor de base de datos. Esto es un poco más de trabajo, pero es mucho mejor. Esto significa que, en lugar de ejecutarrails-app bundle exec rake db:create, simplemente ejecutaría el script para cargar una db.
Tal guión se vería así:
#!/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
donde export.sh ve algo como esto:
#!/bin/bash
set -e
RAILS_ENV=development
rails-app bundle exec rake db:create
mysqldump > /output/setup.sql
También puede reemplazar el script de docker run la docker run con un segundo archivo de redacción si lo desea.