PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : docker



pucki
06.02.19, 00:51
Hallo zusammen,

in Sachen Docker bin ich Anfänger, wenn die Anleitung einigermaßen vernünftig geschrieben ist, dann bekomme ich vorhandene Container eigentlich schon dazu das zu machen was ich möchte. Aktuell kämpfe ich allerdings mit dem offiziellen Container von mariadb. Ich möchte gerne eine Datenbank initialisieren. Zwischenzeitlich bin ich soweit dass die Datenbank und der angegebene Benutzer eingerichtet werden. Nur die Datenbank bleibt leer.

https://hub.docker.com/_/mariadb

ich habe dann mal eine bash im Container geöffnet und festgestellt, dass der Ordner "docker-entrypoint-initdb.d" zwar existiert, aber leer ist. Dann kann logischerweise auch nichts in die Datenbank eingefügt werden. Als workaround könnte ich nun die Daten manuell importieren. Dann weiss ich allerdings immer noch nicht wie ich meinen Dump in den Ordner bekomme, in der er eigentlich automatisch genutzt wird ... das ist irgendwie unbefriedigend. Daher sehe ich den Workaround nur als temporäre Lösung.

Hat das schon mal jemand gelöst? Das Issue #160 hat mir da auch nicht wirklich weiter geholfen ... bei mir kann nichts ausgeführt werden, da nichts da ist ;-(.

Grüße

Reinhard

pucki
06.02.19, 10:18
na ja, man soll das entsprechende Verzeichnis auch als Volume bereitstellen ...

pucki
06.02.19, 11:52
jetzt habe ich doch noch eine Kleinigkeit ...
ich habe jetzt noch ein Fall, wo ich einen Container starten möchte, der nach dem Neustart die Änderungen in der Datenbank automatisch zurücksetzt. Ich kann das Dateisystem nicht auf read-only setzen, man soll ja Anderungen durchführen können.
In der Hilfe habe ich zu einem automatischen Reset nichts gefunden. Aktuell würde das jetzt auf ein Skript raus laufen, dass eine Container stoppt, diesen löscht und dann wieder startet. Wenn da jemand eine andere Idee hat ;-)

Grüße

Reinhard

ThorstenHirsch
06.02.19, 22:26
Du könntest im Dockerfile hinterlegen, dass bei jedem Start ein SQL-Skript ausgeführt wird, das die Datenbank resettet. Das wäre dann im Container statt auẞerhalb.

fork
07.02.19, 08:56
Ich mache das so, dass ich vor dem Aufruf von docker-entrypoint.sh ein Script in den Hintergrund schicke, dass wartet, bis MariaDB hochgefahren ist und das Script sich verbinden kann. Anschließend prüft es anhand der eingestellten Parameter eine SFTP-Adresse, ob dort ein Backup in Form eines Dumps liegt. Wenn dort ein Backup liegt, wird es gezogen und der Dump eingespielt. Anschließend läuft per Cron im Container noch regelmässig ein Dump, der die Dump-Datei an gleiche SFTP-Adresse ablegt.

Sieht dann so aus:

Das von aussen via docker-compose mitgegebene ENV-File(relevanter Ausschnitt):


MYSQL_ROOT_PASSWORD=geheim
MYSQL_ALLOWED_IPS=192.168.1.10 192.168.240.0/24 4.1.123.7
MYSQL_SFTP_BACKUP_SERVER_NAME=mein.sftp.server.dom ain.tld
MYSQL_SFTP_BACKUP_SERVER_PORT=22
MYSQL_SFTP_BACKUP_SERVER_USER=backupuser
SSH_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\niyHTir....P/7j0yOgsQnoL\n-----END RSA PRIVATE KEY-----


app_start Mein Docker-Entrypoint


#!/bin/sh

if [ -f /ENV ] ; then

. /ENV
export MYSQL_ROOT_PASSWORD
/usr/local/bin/setup_ssh_key
/usr/local/bin/setup_iptables

{
/usr/local/bin/mysql_init
/usr/sbin/cron

} >/tmp/mysql_init.log 2>&1 &
fi

# Den ursprünglichen docker-entrypoint aufrufen
/usr/local/bin/docker-entrypoint.sh mysqld

# falls etwas schiefläuft, noch ein sleep, das man den laufenden Container nochmal untersuchen kann
echo
echo sleeping
echo
sleep 3600


mysql_init Die Datenbankinitialisierung


#!/bin/bash

[ -f /ENV ] && . /ENV

echo -e "[mysql]\nuser=root\npassword=$MYSQL_ROOT_PASSWORD\n\n" >/root/.my.cnf
echo -e "[mysqldump]\nuser=root\npassword=$MYSQL_ROOT_PASSWORD\n" >>/root/.my.cnf

# warten bis mariadb mit den übergebenen Zugangsdaten erreichbar ist
/usr/local/bin/wait_for_mysql

# Dump ggf. holen und einspielen
/usr/local/bin/mysql_restore

# Nutzer und Datenbanken, die noch nicht existieren anlegen
/usr/local/bin/initialize-databases
/usr/bin/mysql -e 'flush privileges;'


Grundsätzlich möchte ich später mit Images arbeiten, die in einer Registry abgelegt sind. Da muss ich das noch verbessern, dass die ENV Datei aus den Umgebungsvariablen erzeugt wird und nicht per Dockerfile kopiert wird, denn das geht ja später nicht mehr, wenn nur noch das Image verwendet werden kann. Der Hintergrund ist, das man ein generisches Image ohne Konfigurationsdaten hat, bei dem die Werte beim Starten mitgegeben werden. Also entweder per Umgebungsvariablen(docker), in einer ENV-Datei(docker-compose) oder per Config-Map(kubernetes).

Auch da im Hintergrund noch einen cron laufen zu lassen ist wohl nicht ganz so sauber.

Ich hatte auch schon mal eine Variante mit einem extra Dump-Container. Da ich aber für den Dump-Container ein etwas anderes Setup hatte(Schlankes Alpine Linux Image statt dem offiziellen Mariadb-Image mit Ubuntu), hat das Probleme verursacht, dass mysqldump nicht exakt mit der Version von mariadb zusammengepasst hat(Es gibt da eine Inkompatibilität mit mariadb/mysqldump bei 10.3/10.4 ab der man ein älteres mysqldump nicht mehr verwenden kann.). Um solchen Inkompatibilitäten aus dem Weg zu gehen, habe ich dann beschlossen, den Dump innerhalb des DB-Containers auszuführen.

Dass man iptables verwenden kann, braucht es die docker-Option: --cap-add=NET_ADMIN, der dem Docker-Container auf dem Host-System(!) die Rechte zur Netzwerkverwaltung(Siehe man 7 capabilties).