create - Configurar MySQL e importar volcado dentro de Dockerfile
docker mysql create database (5)
Aquí hay una versión funcional que usa
v3
de
docker-compose.yml
.
La clave es la directiva de
volumes
:
mysql:
image: mysql:5.6
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: theusername
MYSQL_PASSWORD: thepw
MYSQL_DATABASE: mydb
volumes:
- ./data:/docker-entrypoint-initdb.d
En el directorio que tengo mi
docker-compose.yml
tengo un directorio de
data
que contiene archivos de volcado
.sql
.
Esto es bueno porque puede tener un archivo de volcado
.sql
por tabla.
Simplemente ejecuto
docker-compose up
y estoy listo para comenzar.
Los datos persisten automáticamente entre paradas.
Si desea eliminar los datos y "absorber" los nuevos archivos
.sql
, ejecute
docker-compose down
luego
docker-compose up
.
Si alguien sabe cómo hacer que el docker
mysql
vuelva a procesar archivos en
/docker-entrypoint-initdb.d
sin eliminar el volumen, deje un comentario y actualizaré esta respuesta.
Estoy tratando de configurar un Dockerfile para mi proyecto LAMP, pero tengo algunos problemas al iniciar MySQL. Tengo las siguientes líneas en mi Dockerfile:
VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql
Pero sigo recibiendo este error:
ERROR 2002 (HY000): Can''t connect to local MySQL server through socket ''/var/run/mysqld/mysqld.sock'' (111)
¿Alguna idea sobre cómo configurar la creación de la base de datos y la importación de volcados durante una compilación de Dockerfile?
Cada instrucción
RUN
en un
Dockerfile
se ejecuta en una capa diferente (como se explica en la
documentación de
RUN
).
En su
Dockerfile
, tiene tres instrucciones de
Dockerfile
.
El problema es que el servidor MySQL solo se inicia en el primero.
En los demás, no se está ejecutando MySQL, es por eso que obtiene su error de conexión con el cliente
mysql
.
Para resolver este problema tienes 2 soluciones.
Solución 1: use un
RUN
una línea
RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && /
sleep 5 && /
mysql -u root -e "CREATE DATABASE mydb" && /
mysql -u root mydb < /tmp/dump.sql
Solución 2: use un script
Cree un script ejecutable
init_db.sh
:
#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql
Agregue estas líneas a su
Dockerfile
:
ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh
La última versión de la imagen oficial de MySQL Docker le permite importar datos al inicio. Aquí está mi docker-compose.yml
data:
build: docker/data/.
mysql:
image: mysql
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: 1234
volumes:
- ./docker/data:/docker-entrypoint-initdb.d
volumes_from:
- data
Aquí, tengo mi data-dump.sql en
docker/data
que es relativo a la carpeta desde la que se ejecuta docker-compose.
Estoy montando ese archivo sql en este directorio
/docker-entrypoint-initdb.d
en el contenedor.
Si está interesado en ver cómo funciona esto, eche un vistazo a su
docker-entrypoint.sh
en GitHub.
Han agregado este bloque para permitir la importación de datos.
echo
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done
Una nota adicional, si desea que los datos se conserven incluso después de que se detenga y elimine el contenedor mysql, debe tener un contenedor de datos separado como se ve en docker-compose.yml. El contenido del contenedor de datos Dockerfile es muy simple.
FROM n3ziniuka5/ubuntu-oracle-jdk:14.04-JDK8
VOLUME /var/lib/mysql
CMD ["true"]
El contenedor de datos ni siquiera tiene que estar en estado de inicio para persistencia.
Lo que hice fue descargar mi volcado de sql en una carpeta "db-dump" y montarlo:
mysql:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: pass
ports:
- 3306:3306
volumes:
- ./db-dump:/docker-entrypoint-initdb.d
Cuando ejecuto
docker-compose up
por primera vez, el volcado se restaura en la base de datos.
Utilicé el enfoque docker-entrypoint-initdb.d (Gracias a @Kuhess) Pero en mi caso quiero crear mi base de datos basada en algunos parámetros que definí en el archivo .env, así que hice estos
1) Primero defino el archivo .env como este en mi directorio de proyecto raíz de Docker
MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306
2) Luego defino mi archivo docker-compose.yml. Entonces utilicé la directiva args para definir mis variables de entorno y las configuré desde el archivo .env
version: ''2''
services:
### MySQL Container
mysql:
build:
context: ./mysql
args:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- "${MYSQL_PORT}:3306"
3) Luego defino una carpeta mysql que incluye un Dockerfile. Entonces el Dockerfile es este
FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/
ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD
ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
ADD data.sql /etc/mysql/data.sql
RUN sed -i ''s/MYSQL_DATABASE/''$MYSQL_DATABASE''/g'' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d
EXPOSE 3306
4) Ahora uso mysqldump para volcar mi db y poner el data.sql dentro de la carpeta mysql
mysqldump -h <server name> -u<user> -p <db name> > data.sql
El archivo es solo un archivo de volcado sql normal pero agrego 2 líneas al principio para que el archivo se vea así
--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;
-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...
Entonces, ¿qué sucede? Utilicé el comando "EJECUTAR sed -i / MYSQL_DATABASE / ''$ MYSQL_DATABASE'' / g ''/etc/mysql/data.sql" para reemplazar el marcador de posición
MYSQL_DATABASE
con el nombre de mi base de datos que lo configuré en archivo .env.
|- docker-compose.yml
|- .env
|- mysql
|- Dockerfile
|- data.sql
Ahora está listo para construir y ejecutar su contenedor