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_it
yapt-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/sql
con elrails-app bundle exec rake db:create
lines. También deberías proporcionar una configuración de aplicación que llegue a una base de datos enlocalhost:3306
lugar dedb:3306
Mi 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.