Subtiler Unterschied zwischen einem Dockerfile und einer dockercompose Datei – Variablen im Entrypoint Direktiv

TLDR: Variablen in Entrypoints sollten escaped werden. Dies kann durch die Verwendung eines zweiten $ erreicht werden.

Hintergrund

Beim Einrichten eines Spark Thrift Servers stieß ich auf ein – im Nachhinein betrachtet – offensichtliches Versehen. Ich würde immer den folgenden Fehler erhalten, der an sich nur ein Nebeneffekt davon ist, dass ich eine kleine upsy daisy Konfiguration in meiner dockercompose Datei hatte.

org.apache.spark.SparkException: Invalid Spark URL: spark://CoarseGrainedScheduler@:33981

Das Ziel meines Projekts war die Einrichtung eines Spark-Clusters mit Docker Compose einschließlich des Thrift-Servers. Lasset uns in dieses kleine Beispiel eintauchen.

Am Anfang lief noch alles

In meinem Dockerfile hatte ich folgenden Entrypoint:

ENTRYPOINT "/bin/bash", "-c", "DRIVER_HOST=$(hostname -i | tr ' ' '\n' | head -n 1) && echo $DRIVER_HOST && ./sbin/start-thriftserver.sh --conf spark.driver.host=$DRIVER_HOST --conf spark.driver.bindAddress=$DRIVER_HOST"

Dadurch würde der Thrift-Server in seinem eigenen Container laufen. Die Umgebungsvariablen sind so eingestellt, dass sie mit dem Master-Knoten kommunizieren können.

Dann lief alles schief

Die fast exakte Konfiguration, die ich in meine Dockercompose Datei kopiert habe, hat irgendwie dazu geführt, dass der Thrift Server den oben erwähnten Fehler ausgelöst hat.

entrypoint: ["/bin/bash", "-c", "DRIVER_HOST=$(hostname -i | tr ' ' '\n' | head -n 1) && echo $DRIVER_HOST && ./sbin/start-thriftserver.sh --conf spark.driver.host=$DRIVER_HOST --conf spark.driver.bindAddress=$DRIVER_HOST"]

Einige Quellen weisen auf systembedingte Probleme hin (Stackoverflow). Wie wir aber bereits herausgefunden haben, tritt der Fehler nur auf, wenn ich den Befehl im Entrypoint des Dockercompose verwende, nicht aber, wenn er im Dockerfile steht. Der Entrypoint von dockercompose sollte aber theorethisch einfach den im Dockerfile ersetzen und alles sollte wie erwartet funktionieren.

WARN[0000] The “DRIVER_HOST” variable is not set. Defaulting to a blank string.

Asche auf mein Haupt, ich bekenne mich schuldig, Warnmeldungen zu übersehen. Wozu sind sie überhaupt gut? Nun, in diesem Fall meldete diese Meldung nach der Ausführung von docker compose up genau die Ursache, warum meine compose-Konfiguration fehlschlug. Ich war jedoch nicht in der Lage, die Auswirkungen dieser Meldung zu verstehen, bis ich zur Lösung kam. Wohlgemerkt, sogar chatgpt gab mir ein grünes Licht und übersetzte den Entrypoint-Befehl aus dem Dockerfile genau wie oben angeführt für die dockercompose Datei.

Die Fehlersuche ergab schließlich, dass der Code in der Dockerdatei ein DRIVER_HOST echo ausgibt, während der Code in dockercompose dies nicht tut! Dies verursachte den oben erwähnten Fehler.

Auflösung

Aber warum ist das so?

Der Grund dafür ist, dass beim Parsen der dockercompose-Datei die Variablen durch Umgebungsvariablen ersetzt werden, die in der .env-Datei oder in der Umgebung, in der Docker Compose ausgeführt wird, angegeben sind. In diesem Fall wurde jedoch versehentlich eine Variable innerhalb desSkriptes ersetzt, bevor es ausgeführt werden konnte.

Um diese vorzeitige Ersetzung zu verhindern, können wir die Variable $DRIVER_HOST nut einem zusätzlichem $ Zeichen escapen . Auf diese Weise bleibt die Variable während der Parsing-Phase von Docker Compose erhalten und wird während der Ausführung des Skripts innerhalb des Containers korrekt gesetzt (siehe Stackoverflow).

Kommentar verfassen

Your email address will not be published. Required fields are marked *

hungsblog | Nguyen Hung Manh | Dresden
Nach oben scrollen