Crear un contenedor docker mysql con un esquema de base de datos preparado


17

Quiero crear una imagen acoplable sobre la mysql que ya contiene el esquema necesario para mi aplicación.

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

FROM mysql

ENV MYSQL_ROOT_PASSWORD="bagabu"
ENV MYSQL_DATABASE="imhere"

ADD imhere.sql /tmp/imhere.sql

RUN "mysql -u root --password="bagabu" imhere < /tmp/imhere.sql"

A mi entender, eso no funcionó porque la imagen del acoplador mysql no contiene un cliente mysql (el estado de mejores prácticas "no agregue cosas solo porque será bueno tenerlas") (¿estoy equivocado sobre esto?)

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

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

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


Respuestas:


14

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 los documentos de imagen de MySQL Docker .


2
Eso funciona para abrir un contenedor nuevo y cargarlo con mi esquema. ¿Cuál es una buena manera de evitarlo, pero qué sucede si estoy buscando una manera de crear mi propia imagen acoplable que ya tenga el esquema preinstalado?
Tom Klino

En realidad, no importa :-) Pensé que /docker-entrypoint-initdb.destaba en el host, pero en realidad está en el contenedor. Cambié el ADDcomando para copiar a ese directorio y eliminé el RUNcomando. Docker construyó la imagen con éxito y la probé y funciona.
Tom Klino

14

Tenía que hacer esto para propósitos de prueba.

Así es como lo hice al aprovechar 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 init
RUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]

# needed for intialization
ENV MYSQL_ROOT_PASSWORD=root

COPY 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:latest

COPY --from=builder /initialized-db /var/lib/mysql

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


2
La mejor respuesta que he encontrado en todo Internet, la mía fue para postgres, por lo que fue un poco más difícil, pero finalmente funcionó. ¡Y funciona perfectamente!
snowe2010

Las versiones anteriores de mysql (5.7.9) no tienen /usr/local/bin/docker-entrypoint.sh enlazado a /entrypoint.sh, sino que simplemente tienen el entrypoint.sh en /. Cambiar /usr/local/bin/docker-entrypoint.sh a /entrypoint.sh funciona y presumiblemente debería funcionar también para las versiones "modernas".
Marvin

2

Créditos a @Martin Roy

Se hicieron cambios menores para trabajar para mysql ...

Content Dockerfile

FROM mysql:latest as builder

# That file does the DB initialization but also runs mysql daemon, by removing the last line it will only init
RUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]

# needed for intialization
ENV MYSQL_ROOT_PASSWORD=root

COPY 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:latest

COPY --from=builder /initialized-db /var/lib/mysql

Contenido setup.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


-1

El software de administración como Ansible puede ayudarlo a automatizar una importación de mysql fácilmente sin 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.


Eso es interesante: utilicé Ansible pero no lo utilicé para las imágenes de Docker. ¿Puedes extender tu respuesta con algunos ejemplos, Patrick?
Greg Dubicki

Ansible tiene una excelente página de documentos, puede encontrar el módulo de Ansible en esta url: docs.ansible.com/ansible/docker_module.html En cada página del capítulo del módulo de esta guía hay algunos ejemplos.
Patrick
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.