Erstellen eines Docker MySQL-Containers mit einem vorbereiteten Datenbankschema

Ich möchte ein Docker-Image über dem MySQL-Image erstellen, das bereits das erforderliche Schema für meine App enthält.

Ich habe versucht, der Docker-Datei Zeilen hinzuzufügen, die mein Schema als SQL-Datei importieren. Ich habe das als solches getan (meine Docker-Datei):

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"

Nach meinem Verständnis hat das nicht funktioniert, weil das MySQL-Docker-Image keinen MySQL-Client enthält (Best Practices geben an: "Fügen Sie keine Dinge hinzu, nur weil sie schön zu haben sind") (irre ich mich da?)

was könnte ein guter Weg sein, dies zu tun? Ich hatte ein paar Dinge im Sinn, aber sie scheinen alle chaotische Problemumgehungen zu sein.

  1. installieren Sie den MySQL-Client, tun Sie, was ich damit zu tun habe, und entfernen / löschen Sie ihn dann.
  2. kopieren Sie die MySQL-Client-Binärdatei in das Image, tun Sie, was ich tun muss, und entfernen Sie sie dann.
  3. Erstellen Sie das Schema in einem anderen SQL-Server und kopieren Sie die DB-Datei selbst direkt (dies scheint sehr chaotisch zu sein und klingt für mich nach einem kontaminierten Pool von Problemen)

Irgendwelche Vorschläge? Hoffentlich auf eine Weise, die später leicht zu warten ist und vielleicht auch den Best Practices entspricht?

Ich musste das zu Testzwecken machen.

So habe ich die tatsächlichen MySQL / MariaDB-Images auf Dockerhub und den mehrstufigen Build genutzt:

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

Vollständiges Arbeitsbeispiel hier : https://github.com/lindycoder/prepopulated-mysql-container-example

Sie sollten Ihr Init-Skript in einem Verzeichnis ablegen, das als gemountet ist /docker-entrypoint-initdb.d - siehe Abschnitt "Initialisieren einer neuen Instanz" im MySQL-Docker-Image-Dokumente.

Dank an @Martin Roy

Kleinere Änderungen vorgenommen, um für MySQL zu arbeiten...

Inhalt 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 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

Inhalt einrichten.SQL

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

Vollständiges Arbeitsbeispiel hier : https://github.com/iamdvr/prepopulated-mysql-container-example

Dies funktioniert und folgt der Schnittstelle mit dem Mariadb-Einstiegspunktskript. Dateien mit Einstellungen, Tabellen, Daten und Benutzern werden in Ordner kopiert. Wenn der Container gestartet wird, findet das Einstiegspunktskript die Dateien und erstellt eine neue Datenbank.

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

Die Antwort von @ Venkateswara Rao und @ Martin Roy funktioniert hervorragend, wenn es Ihnen egal ist, ob Änderungen an der dockerisierten Datenbank noch in einem Volume enthalten sind. In meinem Fall wollte ich ein mit Daten vorgefülltes Docker-Image, aber in einem Projekt, in dem wir häufige Datenbankmigrationen haben. Daher wollte ich gelegentlich einen DB-Container erstellen, Migrationen ausführen und diese Änderungen dann irgendwie zurückschieben, damit der nächste Benutzer, der das DB-Image verwendet, bereits Migrationen angewendet hat. Da sich die DB-Dateien in einem Volume befinden, werden sie nicht mit in ein Image gerollt docker commmit my-migrated-db-container my-new-db-image.

Meine Lösung war, den Beamten zu benutzen MySQL (5.6 in meinem. fall) Dockerdatei (und Entrypoint-Datei), um ihre Arbeit nach dem Entfernen der VOLUME /var/lib/mysql Linie. Aus dem resultierenden Image habe ich dann die Dateien von Venkateswara verwendet, um ein vorinstalliertes DB-Image zu erstellen, in dem sogar alle zukünftigen DB-Daten im Container selbst gespeichert sind (nicht auf einem Volume).

HINWEIS: Die verknüpfte Dockerfile-Datei ist alt und bezieht sich auf veraltete GPG-Schlüsselserver (dh keys.openpgp.org). Sie können diese Servernamen beispielsweise durch ersetzen, keyserver.ubuntu.com.

Hier ist meine Docker-Datei, die absolut einwandfrei funktioniert./ sql-scripts / enthält Ihre benutzerdefinierte SQL-Datei (mit Ihrer vorbereiteten Datenbank), die ausgeführt wird, sobald der Container ausgeführt wird. Vielleicht möchten Sie sich jedoch die Volume-Montage ansehen.

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

Verwaltungssoftware wie Ansible kann Ihnen helfen, einen MySQL-Import einfach zu automatisieren, ohne einen Client installieren und neu installieren zu müssen.Ansible verfügt über großartige integrierte Funktionen zum Verwalten von Docker-Images, Containern und MySQL-Datenbanken.

Siehe auch: [Wie kann ich eine MySQL-Datenbank mit Schema in einem Docker-Container initialisieren?] (How can I initialize a MySQL database with schema in a Docker container? - Stack Overflow )