Creación de un contenedor mysql de docker con un esquema de base de datos preparado

Quiero crear una imagen de docker sobre la de mysql que ya contenga el esquema necesario para mi aplicación.

Intenté agregar líneas al Dockerfile que importará mi esquema como un archivo sql. Lo hice como tal (mi Dockerfile):

FROM mysqlENV MYSQL_ROOT_PASSWORD="bagabu"ENV MYSQL_DATABASE="imhere"ADD imhere.sql /tmp/imhere.sqlRUN "mysql -u root --password="bagabu" imhere < /tmp/imhere.sql"

A mi entender, eso no funcionó porque la imagen de la ventana acoplable de mysql no contiene un cliente mysql (las mejores prácticas indican "no agregue cosas solo porque será bueno tenerlas") (¿me equivoco en esto?)

¿cuál podría ser una buena manera de hacer esto? He tenido algunas cosas en mente, pero todas parecen soluciones desordenadas.

  1. instale el cliente mysql, haga lo que tenga que hacer con él, luego elimínelo/purgue.
  2. copie el binario del cliente mysql en la imagen, haga lo que tenga que hacer y luego elimínelo.
  3. Cree el esquema en otro servidor sql y copie el archivo db ellos mismos directamente (esto parece muy desordenado y me suena como un grupo de problemas contaminados)

Alguna sugerencia? Con suerte, de una manera que sea fácil de mantener más adelante y tal vez también se ajuste a las mejores prácticas.

Tuve que hacer esto con fines de pruebas.

Así es como lo hice aprovechando las imágenes reales de MySQL / MariaDB en dockerhub y la compilación de varias etapas:

FROM mariadb:latest as builder# That file does the DB initialization but also runs mysql daemon, by removing the last line it will only initRUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]# needed for intializationENV MYSQL_ROOT_PASSWORD=rootCOPY setup.sql /docker-entrypoint-initdb.d/# Need to change the datadir to something else that /var/lib/mysql because the parent docker file defines it as a volume.# https://docs.docker.com/engine/reference/builder/#volume :#       Changing the volume from within the Dockerfile: If any build steps change the data within the volume after#       it has been declared, those changes will be discarded.RUN ["/usr/local/bin/docker-entrypoint.sh", "mysqld", "--datadir", "/initialized-db", "--aria-log-dir-path", "/initialized-db"]FROM mariadb:latestCOPY --from=builder /initialized-db /var/lib/mysql

Ejemplo de trabajo completo aquí : https://github.com/lindycoder/prepopulated-mysql-container-example

Debe colocar su script de inicio en un directorio montado como /docker-entrypoint-initdb.d - consulte la sección "Inicialización de una instancia nueva" en el Documentos de imagen de MySQL Docker.

Créditos a @Martin Roy

Se han realizado cambios menores para que funcionen en mysql...

Dockerfile de Contenido

FROM mysql:latest as builder# That file does the DB initialization but also runs mysql daemon, by removing the last line it will only initRUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]# needed for intializationENV MYSQL_ROOT_PASSWORD=rootCOPY setup.sql /docker-entrypoint-initdb.d/# Need to change the datadir to something else that /var/lib/mysql because the parent docker file defines it as a volume.# https://docs.docker.com/engine/reference/builder/#volume :#       Changing the volume from within the Dockerfile: If any build steps change the data within the volume after#       it has been declared, those changes will be discarded.RUN ["/usr/local/bin/docker-entrypoint.sh", "mysqld", "--datadir", "/initialized-db"]FROM mysql:latestCOPY --from=builder /initialized-db /var/lib/mysql

Configuración de contenido.SQL

CREATE DATABASE myexample;USE myexample;CREATE TABLE mytable (myfield VARCHAR(20));INSERT INTO mytable VALUES ('Hello'), ('Dolly');

Ejemplo de trabajo completo aquí : https://github.com/iamdvr/prepopulated-mysql-container-example

Esto funciona y sigue la interfaz con el script de punto de entrada de mariadb. Los archivos con configuraciones, tablas, datos y usuarios se copian en carpetas. Cuando se inicia el contenedor, el script de punto de entrada encuentra los archivos y crea una nueva base de datos.

FROM mariadb:10.5.5ENV MYSQL_ROOT_PASSWORD=blablablablablablaCOPY settings/my.cnf /etc/mysql/conf.d# comment out !includedir /etc/mysql/conf.d/ to stop recursionRUN sed -i 's/!includedir \/etc\/mysql\/conf\.d\//#!includedir \/etc\/mysql\/conf\.d\//' /etc/mysql/conf.d/my.cnfCOPY db_scripts/db_setup.sql /docker-entrypoint-initdb.d/COPY db_scripts/db_data.sql.template /docker-entrypoint-initdb.d/db_template.sqlCOPY db_scripts/db_users.sql /docker-entrypoint-initdb.d/# Note the port 3306 can be exposed

La respuesta de @Venkateswara Rao y @Martin Roy funciona muy bien si no le importa si los cambios en la base de datos acoplable aún se colocan en un volumen. En mi caso, quería una imagen de Docker prepoblada con datos, pero en un proyecto en el que tenemos migraciones frecuentes de bases de datos. Por lo tanto, de vez en cuando quería hacer un contenedor de base de datos, ejecutar migraciones y luego, de alguna manera, hacer una copia de seguridad de esos cambios para que el próximo usuario que use la imagen de base de datos ya tenga migraciones aplicadas. Dado que los archivos de base de datos viven en un volumen, no se enrollan en una imagen con docker commmit my-migrated-db-container my-new-db-image.

Mi solución fue usar el oficial MySQL (5.6 en mi. caso) Dockerfile (y archivo de punto de entrada) para recrear su trabajo después de quitar el VOLUME /var/lib/mysql alinear. A partir de la imagen resultante, utilicé los archivos de Venkateswara para crear una imagen de base de datos precargada donde incluso todos los datos de base de datos futuros se almacenan en el contenedor en sí (no en un volumen).

NOTA: El archivo Dockerfile vinculado es antiguo y se refiere a servidores de claves GPG obsoletos (es decir , keys.openpgp.org). Puede reemplazar estos nombres de servidor con, por ejemplo, keyserver.ubuntu.com.

Aquí está mi archivo docker que funciona absolutamente bien./sql-scripts / contendrá su archivo sql personalizado (que contiene su base de datos preparada) que se ejecuta una vez que se ejecuta el contenedor. Sin embargo, es posible que desee ver el montaje por volumen.

FROM mysql:5.6COPY ./sql-scripts/ /docker-entrypoint-initdb.d/

El software de administración como Ansible puede ayudarlo a automatizar una importación de mysql fácilmente sin la necesidad de instalar y reinstalar un cliente.Ansible tiene excelentes funciones integradas para administrar imágenes y contenedores de docker y bases de datos mysql.

Consulte también: ¿Cómo puedo inicializar una base de datos MySQL con esquema en un contenedor Docker?