Compose: Interpolieren Sie Umgebungsvariablen in docker-compose.yml

Erstellt am 30. Apr. 2015  ·  109Kommentare  ·  Quelle: docker/compose

(Ich erstelle ein neues Problem dafür, da das alte ziemlich viel Gepäck angesammelt hat.)

Es sollte möglich sein, Umgebungsvariablen an den Wert eines beliebigen * Konfigurationseintrags in docker-compose.yml . Viele Leute wollen es tun, es ist gut für die Portabilität und ich bin zufrieden, dass es kein Chaos verursachen wird.

Ich habe einige Berechnungen.

Erforderliche Variablen und optionale Standardeinstellungen

Es ist nützlich, angeben zu können, dass eine Variable, die in der Umgebung vorhanden sein muss, dh dass Compose die Ausführung verweigert, wenn dies nicht der Fall ist. Dies ist jedoch ein Problem, wenn Sie viele davon haben. Daher sollte es entweder etwas sein, das Sie explizit aktivieren, oder es sollte möglich sein, einen Standardwert anzugeben.

Die MVP-Implementierung muss keine der beiden Funktionen enthalten, es sollte jedoch einen klaren Weg geben, um beide abwärtskompatibel zu implementieren.

Syntax

Es gibt ein starkes Argument für die Implementierung eines etablierten Standards, solange dieser nicht schwergewichtig ist - unsere Anforderungen an die Funktionalität sind minimal.

  • Die Erweiterung der POSIX-Parameter ist in Ordnung. Es hat ein paar zu viele Funktionen, aber wir könnten eine Teilmenge davon implementieren:

    • ${VARIABLE} - gibt eine leere Zeichenfolge aus, wenn VARIABLE ist

    • ${VARIABLE-default} - gibt default wenn VARIABLE ist

    • ${VARIABLE?} - Fehler, wenn VARIABLE ist

https://github.com/docker/compose/pull/845 implementierte eine Bash-artige ${VARIABLE:default} -Syntax, die der POSIX-Parametererweiterung ähnelt, sich jedoch geringfügig unterscheidet.

  • Die Formatsyntax von Python wäre trivial zu implementieren, ist jedoch an die Python-Sprache gebunden und verfügt über zu viele Funktionen.

Implementierung

Die os.path.expandvars -Funktion von Python implementiert den grundlegendsten Fall der POSIX-Parametererweiterung:

>>> from os.path import expandvars
>>> expandvars('${HOME}')
'/Users/aanand'

Es hat jedoch mindestens 2 Probleme:

  1. Eine nicht gesetzte Variable wird nicht zu einer leeren Zeichenfolge erweitert, sondern führt zu keiner Erweiterung:

`` `

expandvars ('$ {UNSET}')
'$ {UNSET}'
`` `

  1. Eine fehlerhafte Syntax tritt nicht auf, sondern führt auch zu keiner Erweiterung:

`` `

expandvars ('$ {HOME')
'$ {HOME'
`` `

Bisher ist https://github.com/docker/compose/pull/845 die nächstgelegene, die wir haben, aber ich bin grundsätzlich vorsichtig bei einer Implementierung, die auf regulären Ausdrücken beruht. Templating ist eine nicht triviale Aufgabe, und die Leute werden alle Arten von kaputten Sachen hineinstecken. Deshalb brauchen wir etwas Robustes, Strenges und Fehler mit hilfreichen Nachrichten. Zwei wichtige Anforderungen:

  • Wenn jemand etwas Falsches einfügt, wird Compose nicht ausgeführt.
  • Es ist möglich, alle in der Vorlagensyntax verwendeten Sonderzeichen zu umgehen.

Möglicherweise gibt es bereits gute Python-Implementierungen für die Bash-ähnliche Variableninterpolation. Andernfalls wäre es weitaus besser, etwas Eigenständiges zu erstellen, als die Compose-Codebasis aufzublähen.

* Gibt es tatsächlich Konfigurationsschlüssel, für die wir keine Interpolation zulassen sollten?

kinenhancement kinfeature

Hilfreichster Kommentar

Mein Anwendungsfall ist es, $PWD in volumes zuzulassen, damit jeder Entwickler im Team ein Repo an jeden Ort klonen kann und die Pfade immer noch korrekt gemountet werden.

elasticsearch:
  image: zinvoice/elasticsearch
  volumes:
    - $PWD:/app

Alle 109 Kommentare

Wie weit möchten Sie mit diesen etablierten UNIX-Standards gehen? (FWIW, es ist kein Defacto-Standard, es ist ein tatsächlicher Standard.)

Als jemand, der gelegentlich versehentlich versucht, POSIX-Parametererweiterungen in Dockerfiles zu verwenden, würde es mich zu einem glücklichen Camper machen, wenn sie überhaupt in docker-compose.yml unterstützt würden.

@kojiromike Hmm , also war die POSIX-Parametererweiterung eigentlich das, was ich wollte, aber beim Lesen der Dokumente sieht es so aus, als hätte ich mich falsch an die Syntax / Semantik erinnert.

Bearbeiten: Ich habe meine Gedanken zur Syntax in der Beschreibung aktualisiert.

Ich bin dem alten Thread gefolgt und wir wollten dringend diese Funktion haben. Schließlich war der Schmerz zu groß und wir haben ein Yaml-Präprozessor-Bahs-Skript erstellt, um Variablen im POSIX-Stil zu ersetzen. es hat gut funktioniert, aber irgendwann haben wir es nicht mehr benutzt, weil es ein Problem gab. Sie müssen zuerst den Präprozessor ausführen und alle Parameter einstellen, bevor Sie die endgültige Lösung erhalten. Jetzt verwenden wir die Docker-Yaml-Erweiterungsfunktion. Weil es uns ermöglicht, die tatsächliche Konfiguration einzuchecken und sie einfach auf dem Ziel auszuführen. Wir wissen besser, was passieren wird.

Obwohl ich ein Befürworter von Docker-Compose-Passing-Variablen war, bin ich mir jetzt nicht so sicher.

Als ideale Lösung würde ich Docker-Erweiterungen lieber richtig machen. In gewissem Sinne wäre das eine Lösung, die zu beiden passt. Also, was ist in Docker erweitert? Es ist im Grunde die Tatsache, dass Sie alle Einträge in die geerbte Datei schreiben müssen. Es ist keine Zusammenführung, bei der Sie nur das eingeben, was Sie überschreiben möchten.

Schauen Sie sich das aktuelle Beispiel an und wie ausführlich es ist. Es sind nur zwei Zeilen wichtig.

#Common 
elasticsearch:
  image: zinvoice/elasticsearch
  hostname: elasticsearch
  restart: always
  dns: 172.17.42.1
  ports:
    - "9200:9200"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro
    - /data/elasticsearch:/opt/elasticsearch/data/elasticsearch

logstash:
  image: zinvoice/logstash
  hostname: logstash
  dns: 172.17.42.1
  restart: always
  ports:
    - "5000:5000"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro

kibana:
  image: zinvoice/kibana
  hostname: kibana
  dns: 172.17.42.1
  restart: always
  ports:
    - "5601:5601"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro

logspout:
  image: zinvoice/logspout
  hostname: logspout
  command: logstash://logstash.docker:5000
  restart: always
  dns: 172.17.42.1
  ports:
    - "8003:8000"
  volumes:
    - /var/run/docker.sock:/tmp/docker.sock

doorman:
  image: zinvoice/doorman
  hostname: doorman
  restart:  always
  dns: 172.17.42.1
  ports:
    - "8085:8085"
# inherited
elasticsearch:
  extends:
    file: ../common.yml
    service: elasticsearch

logstash:
  extends:
    file: ../common.yml
    service: logstash

kibana:
  extends:
    file: ../common.yml
    service: kibana

logspout:
  extends:
    file: ../common.yml
    service: logspout

doorman:
  environment:
    - DOORMAN_GITHUB_APPID=xxxxxxxx
    - DOORMAN_GITHUB_APPSECRET=xxxxxx
  links:
    - nginxtrusted
  extends:
    file: ../common.yml
    service: doorman

Also mein Empfehlungsfix Docker erweitert und macht es weniger ausführlich. Sie müssen nicht einmal so viel Code schreiben, da YAML alle Funktionen bietet, die Sie benötigen. Wenn Sie sich an Standard-YAML halten, kann die Datei von anderen Tools und Benutzeroberflächen analysiert oder erstellt werden.

Werfen Sie einen Blick auf YAML "Node Anchors" und YAML "File Merge". Dies könnte die perfekte Lösung sein.

Zu Ihrer Information: Diese Diskussion wird jetzt auf # 1380 fortgesetzt

@ Vad1mo Ich stimme zu, dass extends in Ihrem Fall nicht ausreicht . Es gibt eine Menge Dinge, die wir tun können, um diese Erfahrung zu verbessern. Könnten Sie ein separates Problem dafür eröffnen, damit wir hier nicht abgelenkt werden?

Na sicher! Ich wollte nur hervorheben, dass dies eine einfache und elegante Alternative sein könnte.
Wenn Sie durch Compose-Erweiterungen die Hälfte der zu variablen Übergabe erhalten, macht eine verbesserte Compose-Erweiterung die Übergabe von Variablen überflüssig. Weniger zu verstehende Konzepte erleichtern dem Benutzer das Arbeiten.

Mein Anwendungsfall ist es, $PWD in volumes zuzulassen, damit jeder Entwickler im Team ein Repo an jeden Ort klonen kann und die Pfade immer noch korrekt gemountet werden.

elasticsearch:
  image: zinvoice/elasticsearch
  volumes:
    - $PWD:/app

@mattes Ich glaube, das wird bereits unterstützt. Ich denke, .:/app wird ebenfalls unterstützt

@aanand Als PoC habe ich ein schmutziges Hackup von POSIX PE in Python durchgeführt . Für die Samstage.

@kojiromike Sieht gut aus. Lassen Sie mich wissen, ob Sie damit fortfahren möchten.

@aanand Ich habe vor, aber es hat definitiv ein paar Fehler im shlex ). Fehlerberichte und PRs sind natürlich willkommen.

@dnephin wie wäre es mit $HOME / ~ ?

@nafg Beide werden für den

@dnephin interessant, b / c irgendwie endete ich mit einem Verzeichnis namens '$ HOME' ...

@aanand Wie der Vorschlag "$ { VARIABLE: default }" mit global_extends (oder "import") würde dies ziemlich mächtig werden.

F: Würde dies die Angabe der Portnummer ermöglichen, die dem Host zur Verfügung steht? wie - "$ {WEB_ PORT: 80 }: 80"?
Der Anwendungsfall besteht darin, auf einfache Weise mehrere Instanzen einer App auf demselben Computer / Cluster hochfahren zu können, wobei normalerweise verschiedene Ports abgehört oder verschiedenen lokalen Domänennamen zugewiesen werden.

Ja, das könnten Sie tun.

Ich möchte vars in Volumes zusammen mit docker-compose scale my_app=3 . Ich habe diese docker-compose.yml

server:
  image: alexanderilyin/docker-teamcity-server
  ports:
   - "8111:8111"
  volumes:
    - .TeamCity:/root/.BuildServer
  links:
   - mysql
mysql:
  image: alexanderilyin/docker-mysql
  volumes:
    - .MySQL:/var/lib/mysql
  environment:
    MYSQL_DATABASE: teamcity
    MYSQL_USER: teamcity
    MYSQL_PASSWORD: teamcity
    MYSQL_ALLOW_EMPTY_PASSWORD: yes
agent:
  image: alexanderilyin/docker-teamcity-agent
  links:
   - server

Und ich möchte in der Lage sein, scale für Agenten zu verwenden und dynamische Volumes für sie zu verwenden, um Daten zwischen den Starts zu speichern, zum Beispiel:

agent:
  image: alexanderilyin/docker-teamcity-agent
  volumes:
    - .agent_{$AGENT_INSTANCE_ID}:/opt/buildAgent
  links:
   - server

Ich hoffe, dass es möglich ist, Variablen auch als Teil des Bildnamens zu interpolieren
Wir verwenden https://github.com/openshift/source-to-image , um für jeden Zweig einen lokalen Container auf CI zu erstellen und dann mit Docker-Compose Tests durchzuführen.
Das Ausführen von Tests mit dynamischem Image ist mit Docker-Compose ziemlich kompliziert und erfordert manuelles Rendern von Vorlagen ..: -1:

Aber Sie können COMPOSE_PROJECT_NAME festlegen, um das Präfix pro Lauf zu steuern, um dies bereits richtig zu machen? In diesem Fall müssen keine komplexe Logik und nicht lesbare XML-Dateien um Namen vorhanden sein.

@andrerom nicht folgen. Laut Dokumenten, die die folgenden Sets the project name, which is prepended to the name of every container started by Compose steuern, während wir stattdessen versuchen, eine Bildeigenschaft festzulegen:

web:
  image: <I_AM_DYNAMIC>

Ah, mein Fehler.

Ich dachte du meintest

<I_AM_DYNAMIC>:
  image: nginx

Eine dynamische Bild- (und Build-) Referenz wäre in der Tat sehr sinnvoll. Beispielsweise wäre ein Wechsel zwischen Debug- und Nicht-Debug-Basiscontainern für Ihre Programmiersprache ein guter Anwendungsfall.

Zusätzlicher Anwendungsfall _ (was @ Maxim-Filimonov möglicherweise im Sinn hat) _: Sie können das zu verwendende Tag eines Bildes überschreiben, sodass Sie Folgendes verwenden können: Standardmäßig, aber ändern, um einfach etwas anderes zu testen, ohne yml zu ändern Datei _ (wird grundsätzlich für CI-Anwendungsfälle benötigt) _.

@andrerom das ist genau unser Anwendungsfall: +1:

Funktioniert das auch für Dinge wie?

web:
  environment:
    - FOO=${whoami}

@ k0377 Ich glaube nicht, dass dies der

In diesem speziellen Fall gibt Ihnen die Umgebungsvariable $USER wahrscheinlich dasselbe.

@aanand Warum nicht eine der vorhandenen Template-Engines verwenden, die bereits vorhanden sind? Jinja2 ist da und funktioniert gut.

Wie bereits erwähnt, ist die Implementierung unserer eigenen Vorlagen keine triviale Aufgabe (und reguläre Ausdrücke sind nicht so cool), sodass wir bereits vorhandene verwenden sollten, die sich als solide erwiesen haben.

Alternativ können wir YAML-Vorfahren und Verweise https://gist.github.com/bowsersenior/979804 verwenden

Dann beschränken wir uns jedoch auf die Verwendung von Variablen (fügen Sie den Variablennamen in die Mitte des Inhalts ein).

+1 für Jinja2: es würde sicherlich in die Form passen und ansible verwendet es für
genau diesen Anwendungsfall (Vorlage in yml-Dateien)

Am Dienstag, den 26. Mai 2015 um 13:25 Uhr schrieb tonnzor [email protected] :

@aanand https://github.com/aanand Warum nicht eine der vorhandenen Vorlagen verwenden ?
Motoren, die bereits vorhanden sind? Jinja2 ist da und funktioniert gut.

Wie bereits erwähnt, ist die Implementierung unserer eigenen Vorlagen keine triviale Aufgabe
(und reguläre Ausdrücke sind nicht so cool), so dass wir bereits vorhandene verwenden sollten,
das erwies sich als solide.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment -105493447.

Jinja2 macht viel mehr als wir brauchen:

  • Bedingungen
  • Schleifen
  • Erweiterung / Vererbung
  • Bemerkungen
  • Filter

Wir fügen Compose nichts davon hinzu. Wenn Jinja2 so konfiguriert werden kann, dass nur Variablen interpoliert werden, ist dies möglicherweise ein Kandidat.

Eigentlich könnte Looping interessant sein.

Angenommen, Sie haben eine Liste von Kunden, für die Sie Container starten möchten
Hier fügen Sie einige kundenspezifische Variablen in die Umgebung ein.

Erweiterung / Vererbung könnte interessant sein, um den Strom zu verbessern
rudimentärer Verlängerungsmechanismus.

Filter können großartig sein, um etwas mit vorhandenen Variablen zu tun.

Am Dienstag, den 26. Mai 2015 um 13:56 Uhr, Aanand Prasad [email protected]
schrieb:

Jinja2 macht viel mehr als wir brauchen:

  • Bedingungen
  • Schleifen
  • Erweiterung / Vererbung
  • Bemerkungen
  • Filter

Wir fügen Compose nichts davon hinzu. Wenn Jinja2 konfiguriert werden kann
Um nur Variablen zu interpolieren, könnte es sich um einen Kandidaten handeln.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment -105498909.

Sie könnten interessante Funktionen sein, aber sie sind weitaus komplexer, als ich es mir vorstellen kann, sowohl Compose als auch das Dateiformat einzuführen, und wir würden beide an eine bestimmte Vorlagensprache mit (soweit ich weiß) einer einzigen Implementierung binden und keine spez. Es ist einfach nicht machbar.

@aanand Einige Anmerkungen hier:

  1. Jinja2 ist solide und es dauert Minuten, um YAML damit vorzuverarbeiten:

aus jinja2 importieren Vorlage
template = Template ('Hallo {{Name}}!')
template.render (name = "Aanand")
Hallo Aanand!

Wenn Sie mehr Sicherheit wünschen, können Sie eine unveränderliche Sandbox verwenden:

aus jinja2.sandbox importieren ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Hallo {{name}}!')
template.render (name = "Aanand")
Hallo Aanand!

In unserem Fall wäre es:

os importieren
aus jinja2.sandbox importieren ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Hallo {{name}}!')
template.render (** os.environ)

  1. Wollen wir keine Filter? Mit dem Filter können Sie den Standardwert einfach definieren ({{value | default ("default")}}).
  2. Müssen wir uns wirklich um Benutzer kümmern, die erweiterte Jinja-Funktionen verwenden, um YAML-Dateien zu verschrauben? Auf die gleiche Weise könnte der Benutzer eine ungültige YAML-Datei manuell erstellen. Ich denke, wir sollten es einfach halten - versuchen Sie, die angegebene Jinja-Vorlage zu verarbeiten und einen Fehler zurückzugeben, wenn ein Fehler aufgetreten ist oder die erzeugte YAML ungültig ist (genau wie jetzt).
  3. Wenn Sie Jinja2 nicht als Lösung sehen, wäre es zumindest großartig, {{variable}} als Syntax zu verwenden.
  4. Django verwendet Regexp, um Vorlagen zu analysieren und zu generieren. Es ist seit langem produktionsfähig und lebt gut damit.

os importieren
import re
template = "Hallo {{name}}!"
re ("{{\ s _ ([a-zA-Z0-9 _] +?) \ s_}}", Lambda m: os.environ.get (m.group (1), ''), Vorlage)

In jedem Fall muss diese Funktion verfügbar sein, unabhängig davon, welche Lösung wir wählen.

Ich bin +1 bei der Verwendung einer generischen Vorlagenlösung, wenn Vorlagen berücksichtigt werden. ZB http://mustache.github.io , das in vielen Sprachen verfügbar ist. Dies ist nur ein Beispiel, andere Templating-Engines können gleichermaßen berücksichtigt werden

@aanand ich verstehe deinen Punkt total. Ich mag auch die Einfachheit und
Prägnanz der Komposition dsl.

Vielleicht sollte dies als externes Projekt durchgeführt werden, sagen Metakomponisten. Es
Nimmt eine compose.tpl.yml und eine variables.yml, erstellt eine docker-compose.yml
und los geht's.
Wie @tonnzor gezeigt hat, kann man mit einem winzigen Stück Python-Code arbeiten.

Dies würde denjenigen, die es ohne brauchen, mächtige Vorlagen liefern
Komplexität für einfache Aufgaben einführen.

Am Dienstag, den 26. Mai 2015 um 16:52 Uhr, Sebastiaan van Stijn <
[email protected]> schrieb:

Ich bin +1 bei der Verwendung einer _generischen_ Vorlagenlösung, wenn Vorlagen vorhanden sind
berücksichtigt. ZB http://mustache.github.io , das in vielen verfügbar ist
Sprachen. Dies ist nur ein Beispiel, das andere Template-Engines sein können
gleichermaßen berücksichtigt

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Hmm… Also ist der Vorschlag jetzt, eine Vorlagensprache in compose.yml (eine beschreibende Sprache zum Erstellen von Docker-Containern) für Dinge wie command und entrypoint , die bereits beide exec akzeptieren sh -c Stilwerte? Dies könnte verwirrend sein, da der resultierende Shell-Befehl nach dem Rendern der Vorlage vermutlich immer noch interpretiert wird. Wenn also eine Variable auf * sie weiter global erweitert. Das Entkommen von Sequenzen in der einen oder anderen Sprache wird schwierig, wenn Sie so viele Ebenen der Fall-Through-Interpretation haben.

@kojiromike Ich bin mir nicht sicher, ob eine Template-Engine gesucht wird, aber wenn sie verwendet werden soll! Verwenden Sie besser etwas Bekanntes. Die Grundfrage ist: sollte Docker-Compose die Substitution von Grund auf neu schreiben oder etwas Vorhandenes verwenden.

Am Dienstag, 26. Mai 2015, 11:02 Uhr Christoph Witzany [email protected]
schrieb:

@aanand ich verstehe deinen Punkt total. Ich mag auch die Einfachheit und
Prägnanz der Komposition dsl.

Vielleicht sollte dies als externes Projekt durchgeführt werden, sagen Metakomponisten. Es
Nimmt eine compose.tpl.yml und eine variables.yml, erstellt eine docker-compose.yml
und los geht's.

Das können Sie heute ohne neues Projekt tun. Ich bin sicher, Jinja kann sein
irgendwie von der Kommandozeile aufgerufen. Persönlich benutze ich nur den envsubst
Befehl.

Was wirklich hilfreich wäre, wäre, wenn compose die Datei von stdin lesen könnte.
Das würde die Notwendigkeit einer Zwischendatei beseitigen.

Wie @tonnzor gezeigt hat, kann man mit einem winzigen Stück Python-Code arbeiten.

Dies würde denjenigen, die es ohne brauchen, mächtige Vorlagen liefern
Komplexität für einfache Aufgaben einführen.

Am Dienstag, den 26. Mai 2015 um 16:52 Uhr, Sebastiaan van Stijn <
[email protected]> schrieb:

Ich bin +1 bei der Verwendung einer _generischen_ Vorlagenlösung, wenn Vorlagen vorhanden sind
berücksichtigt. ZB http://mustache.github.io , das in vielen verfügbar ist
Sprachen. Dies ist nur ein Beispiel, das andere Template-Engines sein können
gleichermaßen berücksichtigt

Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment -105554730. src = "
https://ci6.googleusercontent.com/proxy/iSBXyl7D8PwFM4p1mGPHCR7bQctunieGbhyGkvo0QIMIjmAYE3I0Mt96yl1fGrqcuOzxV4APP8ZRIw-5_qd6nzps9Mpr6jTAydCC4xs8JDgqm93aIbWvN1eMlxykrz7iwYooyAQdqL4RFJokeEbnBkZm5mhgKg=s0-d-e1-ft#https://github.com/notifications/beacon/AAGAUO8xqz29B2SUoG7QFPUy848_JJW9ks5oNIJlgaJpZM4EMysO.gif
">

+1 zum Lesen der Datei von stdin. Ich habe kein Problem mit der Verwendung einer externen Vorlagenlösung, aber es wäre schön, keine Zwischendateien zu haben.

Das klingt nach einem großartigen ersten Schritt und ist ein gemeinsames Merkmal vieler CLI-Tools. Lass uns das tun

: +1:

So zum Beispiel

envsubst compose.tmpl.yml | docker-compose -f - up -d

wfm. : +1:

Ich habe gerade festgestellt, dass Docker / Distribution über Umgebungsvariablen überschreibende Werte in der yml-Datei verarbeitet, jedoch einen anderen Ansatz verwendet: https://github.com/docker/distribution/blob/master/docs/configuration.md#override -configuration-options

^^ @aanand

@thaJeztah das würde auch bei uns funktionieren. Wir können dann Umgebungsvariablen verwenden, um Befehle zu überschreiben

DOCKER_COMPOSE_IMAGE_NAME='my_image:is_dynamic'

Interessanter Ansatz, aber ich bin kein Fan - ausführliche Umgebungsvariablennamen, viel Duplizierung, wenn Sie einen Wert an mehreren Stellen verwenden möchten, alles implizit, keine Interpolation innerhalb von Zeichenfolgen.

@aanand hat diesen Ansatz auch nicht wirklich verkauft, wollte aber darauf hinweisen, da es sich um ein weiteres Projekt innerhalb der "Docker" -Organisation handelt.

Ich bin gerade auf https://github.com/kelseyhightower/confd gestoßen, was von Interesse sein könnte. Es verwendet http://golang.org/pkg/text/template/#pkg -overview

@olalonde leider ist Docker-Compose in Python geschrieben, so dass Go-Vorlagen nicht funktionieren.

@aanand Ich bin +20 auf Ihrem ursprünglichen Vorschlag, mit der Optimierung, dass sogar Bilder und insbesondere Tags möglich sein sollten, zu injizieren. Mach es einfach, würde uns allen eine Menge Wrapper und unnötige Konfigurationshandhabung ersparen;)

Ich habe ein kleines Python-Paket geschrieben, das mir dabei hilft. Es ist geplant, alle Befehle zu docker compose zu tunneln, damit Sie sie gleichwertig verwenden können.
Überprüfen Sie es unter https://github.com/webcrofting/meta-compose/

Meta-Compose sieht wirklich gut aus. Es sollte zum Docker-Compose integriert werden!

Big +1 hier - Ich bin nicht begeistert von der Vorverarbeitung von Vorlagen, aber das Ziehen von Umgebungsvariablen auf die eine oder andere Weise wäre großartig. Die POSIX-Erweiterung ist wahrscheinlich sauberer als Jinja2, aber in beiden Fällen ist sie in Ordnung.

Big +1 von hier auch. Mein Anwendungsfall ist eher das Hinzufügen einer dynamischen Werbe-ID-Unterstützung für Kafka-Container, die für Hersteller von Daten (die andere Container sein könnten) von entscheidender Bedeutung ist.

Ich freue mich auch über diese Funktion.

Die POSIX-Erweiterung ist wahrscheinlich sauberer als Jinja2, aber in beiden Fällen ist sie in Ordnung.

Ich denke, ein weiteres Argument für die POSIX-Erweiterung ist, dass es keine Logik enthält. Jinja2 unterstützt ein gewisses Maß an Bedingungs- / Schleifenlogik (wie die meisten Template-Engines, auch diejenigen, die behaupten, "logiklos" zu sein). Das Mischen von Template-Logik und YAML ist meiner Erfahrung nach ziemlich seltsam. Kann sich jemand einen Anwendungsfall für eine solche Logik vorstellen? Wenn nicht, ist es möglicherweise am besten, die Unterstützung vorerst ausdrücklich zu vermeiden.

Es wäre schön, eine klare Antwort von Entwicklern zu dieser Funktion zu haben. Beim Lesen verschiedener Themen und PR ist nicht klar, ob Sie es wirklich implementieren möchten oder nicht.

Wenn ja, mit welchem ​​Mechanismus? Wenn Sie dies nicht tun, können Benutzer Tools von Drittanbietern erstellen, um die Funktion zu verwalten.

Vielen Dank !

Ok, ich habe gerade https://github.com/docker/compose/pull/76 gesehen. Ich denke die Antwort ist da ...

Ging ein paar Zyklen über die verknüpften Themen / PRs.

AFAIK, nginx community lehnte es ab, eine Template-Engine für Konfigurationsdateien zu verwenden, selbst für eine einfache Variablensubstitution. Warum? Vielleicht wählen sie immer noch eine ideale Template-Engine: smile:. Ergebnis? Schmerz (relativ)!

@ Hadim

Beim Lesen verschiedener Themen und PR ist nicht klar, ob Sie es wirklich implementieren möchten oder nicht.

Dieses Problem sollte die endgültige Antwort auf diese Frage liefern. Es tut mir leid, dass ich nicht klar war: Ja, wir möchten es implementieren und mit einer POSIX-Syntax.

danke @aanand !

Danke, @aanand.

+1 für mich. Ich muss --dns = (Adresse der Docker0-Brücke) übergeben, und es muss funktionieren, wenn sich dies in zukünftigen Versionen von Docker jemals ändert, sodass eine Umgebungsvariable und / oder Shell perfekt ist. meta-compose funktioniert bei mir nicht, da es remote DOCKER_HOST und zB über Docker-Swarm unterstützen sollte, nicht nur lokal.

: +1: Das wäre sehr schön. Derzeit generiere ich entweder die .yml-Datei über ein anderes Skript oder verwende Docker-Compose nicht vollständig und verknüpfe Docker manuell.

:Daumen hoch:

Ich denke, eine grundlegende Interpolation von Umgebungsvariablen wäre für einfache Dinge sehr nützlich.

Einige einfache Anwendungsfälle:

  • In der Lage sein, das Tag eines Images, das aus einem Remote-Repository abgerufen werden soll, dynamisch anzugeben.
  • In der Lage sein, die Portzuordnung für einen Container festzulegen.

Tools wie Ansible eignen sich bereits sehr gut für Vorlagen, daher bin ich mir nicht sicher, ob eine vollständige Vorlagen-Engine erforderlich ist. Es ist jedoch sehr einschränkend, keinen dynamischen Inhalt in der Datei comose.yml zu haben.

In Bezug auf die zusammengeführte PR # 1488 bin ich besonders daran interessiert, eine Konfigurationsdatei an docker-compose . Ich kann nicht verstehen, warum docker-compose nicht von einem Knotenprozess aufgenommen werden kann.

var spawn = require('child_process').spawn;

var compose = spawn('docker-compose', ['--file' + '-' + 'up']);

compose.stdin.setEncoding = 'utf-8';

compose.stdout.on('data', function (data) {
    console.log('"docker-compose --file - up" stdout: "%s".', data);
});

compose.stderr.on('data', function (data) {
    console.log('"docker-compose --file - up" returned an error: "%s".', data);
});

compose.on('close', function (code) {
    if (code !== 0) {
        console.log('"docker-compose --file - up" existed with an erroneous code: "%s".', code);
    } else {
        console.log('"docker-compose --file - up" existed with code: "%s". SUCCESS!', code);
    }
});

compose.stdin.write("redis: {\"image\": \"redis\"}\n");
compose.stdin.end();

Gibt es Beispiele zum Weiterleiten von Daten aus Node.js?

Eine andere Sache, die ich gefunden habe, ist, dass docker-compose 1.4.0-RC1 einige scheinbar normale Nachrichten wie Starting... oder Attaching... an stderr anstelle von stdout sendet

@kadishmal Könnten Sie bitte separate Ausgaben für diese öffnen?

Eine weitere mögliche Syntax / Implementierung: Pythons String-Template, wie in PEP 0292 angegeben und in string.Template implementiert.

Es ist der POSIX-Parametererweiterung sehr ähnlich:

  • $foo auf den Wert von foo
  • ${foo} auf den Wert von foo
  • $ , ${ , $} , ${} , ${foo , $ {foo} , ${ foo} , ${foo } sind Fehler

Nachteile:

  • Kein Standardwert oder "Erforderlicher Wert" -Syntax. Dennoch könnten wir später entscheiden, ob wir möchten, dass diese genug sind, um unseren eigenen Vorlagencode zu schreiben.
  • Die Fehlermeldungen enthalten keine maschinenlesbaren Informationen darüber, wo sich der Syntaxfehler befindet (dh ohne Regex-Matching für die Fehlerzeichenfolge).
  • Die Escape-Syntax unterscheidet sich von POSIX: $$ anstelle von \$ .

Dies könnte tatsächlich ein Segen in der Verkleidung sein: YAML mag \$ und erfordert, dass Sie doppelt entkommen. Ich glaube nicht, dass es fliegen wird, wenn man den Leuten sagt, sie sollen \\$ eingeben, nur um ein Dollarzeichen zu bekommen.

Ich habe eine Implementierung in # 1765 herausgebracht.

+1

Ich bin mir nicht sicher, ob dies der richtige Ort dafür ist oder ob ich eine neue Ausgabe machen sollte.

Ich denke, die env-Priorität sollte umgekehrt sein, dh eine Variable aus der Shell, die Docker-Compose aufruft, sollte jede Variable in docker-compose.yml überschreiben, die wiederum jede vom Container definierte Variable überschreiben sollte.

Folgendes passiert derzeit, wenn ich es versuche:

docker-compose.yml:

test:
    image: ubuntu
    environment:
        - FOO="from compose"

und führen Sie es dann mit dem Befehl env :

docker-compose run test env | grep FOO

gibt FOO="from compose" wie erwartet. Aber dann:

FOO="from shell" docker-compose run test env | grep FOO

gibt auch FOO="from compose" , aber hier hatte ich FOO="from shell" erwartet.

Einige Benutzer benötigen möglicherweise auch noch eine variable Interpolation für andere Anwendungsfälle, aber eine Änderung würde den "Standard" -Fall erfüllen - effektiv ist die Definition / der Wert environment: in docker-compose.yml die Standardeinstellung und kann überschrieben werden bei Bedarf zur Laufzeit, ohne dass eine zusätzliche YAML-Syntax erforderlich ist.

@fazy Sie haben nicht berücksichtigt, dass der Befehl env in dem isolierten Container test ausgeführt wurde, in dem der FOO from compose (nur wie es sein sollte und wie es in einer docker-compose Datei konfiguriert wurde). Aber außerhalb dieses Containers hätte der docker-compose -Prozess eine Art Druckfunktion für die Umgebungsvariable, die Sie vor dem Befehl eingerichtet haben, "von der Shell" gedruckt, da dies der Wert für den Host (sowie für) ist den docker-compose -Prozess), auf dem Sie ihn ausführen. Vielleicht haben Sie erwartet, dass der Wert von from shell in diesem Fall FOO beträgt, aber ich persönlich wäre ziemlich überrascht, wenn dies der Fall wäre. (Ich hoffe, dass Sie trotz meines Englisch meinen Standpunkt verstehen werden).

@smileart danke, ich glaube ich sehe was du sagst.

Der test -Container ist jedoch nicht vollständig isoliert. Er erhält seine Umgebung von docker-compose (oder zumindest kann Docker-Compose Umgebungsvariablen in den gestarteten Container setzen) und Docker-Compose selbst kann die "äußere" Umgebungsvariable sehen.

Sie können mit dieser docker-compose.yml sehen:

test:
    image: ubuntu
    environment:
        - FOO

Dann der Befehl:

FOO="from shell" docker-compose run test env | grep FOO

gibt in der Tat das "from shell" -Ergebnis.

Meine Frage hat also Vorrang. Wenn Sie hier nur den Variablennamen - FOO angeben, kann ich die Variable von außen injizieren. Aber wenn ich - FOO=something _und_ spezifiziere und eine Variable von außen injiziere, welche sollte Vorrang haben? IMHO sollte die in der Befehlszeile angegebene Variable Vorrang vor der Konfigurationsdatei haben.

@fazy Oh, tut mir leid, ich habe FOO="from shell" docker-compose run test env | grep FOO nicht ausprobiert, ohne seinen Wert in docker-compose.yml anzugeben, und ich wusste nicht, dass es uns den FOO Hosts gibt. Es wäre also nicht nur schon seltsam für mich: smiley: Ich dachte, das Einrichten einer Umgebungsvariablen vor docker-compose beeinflusst NUR docker-compose und docker-compose ohne sie in die zu werfen Container. Jetzt verstehe ich, was du gemeint hast.

Ich bin gerade auf den Nachteil gestoßen, $ entkommen, der in https://github.com/docker/compose/issues/1377#issuecomment -124571722 erwähnt wurde. Zuerst habe ich nur FOO=ba$e dann FOO='ba$e' (wobei ich vergessen habe, dass es "nackt" ist), dann FOO=ba\$e , dann FOO=ba\\$e , dann habe ich aufgegeben und bin zu gegangen die Dokumente, nur um überrascht zu sein, dass " $ das Fluchtzeichen für $ ". Für mich war dies nicht besonders "am wenigsten überraschend".

Ich weiß jedoch nicht, was die gute Lösung wäre.

@ ct-clearhaus Compose ist nicht das einzige Programm , das verwendet $ für die Flucht $ . Sie finden dies auch in Makefiles. Für manche Menschen ist diese Redewendung also recht vertraut.

Ich liebe die vorhandene Implementierung der Variablensubstitution . Ich könnte jedoch wirklich die Möglichkeit nutzen, einen Standard gemäß dem ursprünglichen Vorschlag von

${ENV-default}

Meine spezielle Verwendung besteht darin, dass ich den Host-Port angeben möchte, auf dem der Dienst ausgeführt wird:

PORT=8123 docker-compose up

Indem ich dies zu meinem docker-compose.yml hinzufüge:

web:
  ports:
    - "${PORT-8000}:5000"

Ist diese Funktion noch geplant und in Vorbereitung?

Ich habe versucht, mein Problem mit Extends zu lösen, aber es wurde ziemlich chaotisch. Ich musste nicht nur fast alle meine docker-compose.yml duplizieren, um nur eine Einstellung zu ändern, es gibt auch keine Möglichkeit, eine exponierte Porteinstellung zu ändern. Sie können nur add to die Liste der exponierten Ports anzeigen, die ist nicht ideal für mich.

Warum schlägt Docker-Compose nicht fehl, wenn keine Umgebungsvariablen festgelegt sind? Es wird nur eine Warnung protokolliert und fortgesetzt. Wäre nicht nur Rückkehr und Fehler ein besserer Ansatz ...
WARNING: The FOO variable is not set. Defaulting to a blank string.

+1 für die POSIX-Syntax zum Deklarieren von Standardwerten

Vielleicht fehlt mir etwas Offensichtliches, aber ich möchte Umgebungsvariablen aus einer env_file verwenden können, um den Wert einer Umgebungsvariablen festzulegen, z.

docker-compose.env:

DB_PASSWORD=test

docker-compose.yaml:

...
service:
    database:
        env_file:
            - ./docker-compose.env
        environment:
            - MYSQL_PASSWORD=${DB_PASSWORD}
    webserver:
        env_file:
            - ./docker-compose.env
        environment:
            - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}

Könnte es auf andere Weise erreicht werden? Ich möchte keine Yaml-Vorlagendatei haben, die durch envsubst geleitet werden muss.

Warum setzen Sie diesen Wert nicht einfach so direkt in env_file wie Sie es möchten?

2636 unterstützt eine env-Datei für Standardwerte

Das würde bedeuten, dass eine Variable, die an zwei Stellen den gleichen Wert haben muss, einfacher ist, wenn Sie nur eine ändern müssen. # 2636 sieht vielversprechend aus.

Benötigen Sie dringend einen Mechanismus, um jetzt Standardvariablen zu unterstützen, da bestehende Einschränkungen uns zwingen, Wrapper-Skripte zu verwenden, um Docker-Compose zu unterstützen. Ich brauche Dinge wie NODE_ENV=${NODE_ENV:-dev} zu arbeiten, und der Einfachheit halber wäre es schön, wenn SOME_NUMBER=$((96*60)) arbeiten würde. War dies für eine kommende Version geplant?

+1 für Standardwerte

+1 für Standardwerte. Das wird für uns immer wichtiger.

Ich stimme @ darkn3rd zu - Ich muss die Benutzer-ID und die Benutzergruppen-ID einzurichten . Die einzige Möglichkeit, die ich gefunden habe, besteht darin, mein Team zu zwingen, 2 Variablen zu exportieren ... oder ein Makefile zu verwenden, das ich zum Exportieren erstellt habe.

Wenn ich nur kann:

    user: $((id -u)):$((id -g))

das wird meine gesamten Probleme lösen

@mgor Klingt so, als könntest du es einfach durch envsubst ?

env $(cat docker-compose.env | xargs) envsubst < docker-compose.tmpl > docker-compose.yml

sollte es tun (ohne die anhaltende Umwelt zu verschmutzen), denke ich.

@OJFord @mgor Keine Absicht, den Thread hochzuziehen, aber ich habe ein paar CLI-Tools erstellt, um einen saubereren Workflow zu erzielen. envset und slv .

envset development -- slv docker-compose.tpl > docker-compose.yml

envset lädt Variablen aus einer env-Datei in die aktuelle Shell-Sitzung, slv ersetzt Vorlagen mithilfe von Umgebungsvariablen.

Ich stimme @OJFord zu, aber das brauche ich nicht ...
Lassen Sie mich genau sagen: Wir sind ein Team von 40 Entwicklern, die verschiedene Docker-Compose-Stacks verwenden. Wir verwenden git, um Code zu erhalten.

Wenn ich sie auffordere, die von unserem Git gelieferte Datei docker-compose.yml zu ändern, bin ich sicher, dass jemand eine geänderte Datei docker-compose.yml pushen wird ... Vertrauen Sie mir, das wird der Fall sein.

Ich kann "eine Basis-Composer-Datei generieren", die von git ignoriert und von docker-compose.yml erweitert wird, aber um sie zu generieren, muss ich ihnen ein Makefile oder ein Bashscript geben ... Der Tag wird kommen, an dem eine "Basis" entsteht Docker-Datei "Änderungen sind erforderlich, und das Team weiß nicht, dass die Generation erneut ausgeführt werden muss.

Das gleiche gilt für eine "env" -Datei, das ist sehr schön, aber es funktioniert nicht mit "build" und ich muss mein Team bitten, diese Datei zu generieren.

Wirklich, wenn Docker-Compose Werte von bash (oder einer anderen Lösung, die etwas anderes als eine ENV-Variable zurückgibt) in der yaml-Datei erhalten kann, werden viele Anforderungen gelöst.

Mein Beispiel in meinem vorherigen Befehl ist perfekt: Ich muss Benutzer-ID und GID abrufen, und diese Werte werden nicht von ENV-Variablen festgelegt. Also muss ich mein Team bitten, ihre IDs in eine .env-Datei zu schreiben ... Einfach für mich und Sie, nicht für alle.

Genauer gesagt: Ich muss eine Docker-Compose-Datei angeben, die vom Team nicht geändert werden sollte, da sie sich in einem Git-Repository befindet.

Diese Pull-Anfrage ist ein einfaches Beispiel, das für mich funktioniert. Vielleicht kannst du mir helfen, es besser zu machen.

Ich habe es mit Umgebungs- und Benutzeranweisungen aus der Datei docker-compose.yml versucht. Funktioniert vorerst gut.

Der Standardwert sollte vorhanden sein ... Sehr nützlich ... Entwickler und OPS verwenden entweder die Docker-Protokolle oder das Syslog ... Daher müssen sie normalerweise das unten gezeigte Standard-

default:
  extends:
    file: base.yml
    service: base-${LOG_FORMAT:docker}
  labels:
    - "net.company.npmjs.datacenter=${DATA_CENTER}"
    - "net.company.npmjs.env=${ENV}"
    - "net.company.npmjs.hostname=${HOSTNAME}"
    - "net.company.npmjs.role=${NPMO_ROLE}"
    - "net.company.npmjs.log=${LOG_FORMAT}"

base-syslog:
  log_driver: syslog
  log_opt:
    tag: "{{.ImageName}}/{{.Name}}/{{.ID}}"

base-docker:
  log_driver: json-file
  log_opt:
    max-size: "128m"
    max-file: "4"

Wann wird dies verfügbar sein? Ich bin auf Compose 1.7.0 und das ist immer noch nicht da :(

Bitte, bitte, bitte geben Sie uns Standardwerte!

@marcellodesales : Vielleicht können Sie die Verwendung einer docker-compose.override.yml -Datei auf irgendeine Weise nutzen. Überprüfen Sie diese Funktion.

Auch +1 auf env vars. Es ist heutzutage unser Hauptschmerzpunkt bei Docker-Compose.

Ich würde auf meiner PR # 3367 bestehen, um bestimmte Werte vom Host erhalten zu können. :) :)

@pataquets Ich glaube nicht, dass ich noch eine andere Override-Datei erstellen möchte ... unsere base.yml -Datei zeigt, wie oben gezeigt, alle unterstützten Dinge in Bezug auf den Logger-Treiber usw. Ich möchte nur wechseln und haben Standardwerte. Ich würde denken, dass wir noch mehr yml-Dateien pflegen müssten. Aber ich werde das für alle Fälle berücksichtigen.

+1

+1

+1

+1

Gibt es Hinweise zur Verwendung von Umgebungsvariablen in Docker-Compose?

+1

+1

Zu Ihrer Information: Umgebungsvariablen für Docker-Compose funktionieren ab 1.7.0. Sie können Docker-Compose-Standardvariablen auch in .env im selben Verzeichnis wie Ihre Root-Datei docker-compose.yml festlegen. Dies ist nicht mit Docker-Engine-Envfiles zu verwechseln, da dies eine andere Sache ist.

Gibt es eine Möglichkeit, den Dienstnamen als Variable festzulegen?

Anstatt dies zu schreiben

services:
   site_db:
     image: mysql:5.7

Wir könnten schreiben

services:
   ${CONTAINER_NAME}:
     image: mysql:5.7

Mein Ziel ist es, dasselbe docker-compose.yml auf mehreren Websites beizubehalten und nur die .env -Datei zu ändern. Im Moment muss ich den Containernamen noch ändern, da ich mehrere Apps auf demselben Host ausführe. Und ich möchte, dass jeder Dienst aus Gründen der Klarheit einen eigenen Namen hat.

@ LouWii können Sie verwenden

services:
    site_db:
      container_name: "${CONTAINER_NAME}"
      image: mysql:5.7

oder (Compose-File-Format 2.1 und höher)

services:
    site_db:
      container_name: "${CONTAINER_NAME:-defaultname}"
      image: mysql:5.7

Aber warum nicht den Projektnamen festlegen? Der Projektname ist dafür _intended_, da er den Containernamen, die erstellt werden, um Konflikte mit anderen Projekten auf demselben Host zu vermeiden, Präfixe / Namespaces hinzufügt. Siehe https://docs.docker.com/compose/reference/envvars/#/composeprojectname

@thaJeztah Danke! Ich lerne immer noch, wie Docker und Docker komponieren. Das Festlegen des Projektnamens scheint eine bessere Option zu sein, was für mich völlig sinnvoll ist.

Gibt es eine Möglichkeit, innerhalb der interpolierten Klammern ein Skript zu erstellen? Zum Beispiel ${HOST_PORT + 1} .

Sie könnten die Datei durch Jinja leiten oder so ...

Am Dienstag, 24. Januar 2017, 05:36 Uhr Sam A. Horvath-Hunt [email protected]
schrieb:

Gibt es eine Möglichkeit, innerhalb der interpolierten Klammern ein Skript zu erstellen? Zum Beispiel $ {HOST_PORT

  • 1}.

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/docker/compose/issues/1377#issuecomment-274767368 ,
oder schalten Sie den Thread stumm
https://github.com/notifications/unsubscribe-auth/AAGAUN5ZrU39dnVVVASwIHr5mGqJFxh3ks5rVdRIgaJpZM4EMysO
.

Kann ich $ entkommen?

environment:
   PATH: "$PATH:/home/appuser/.bundler/bin"

Derzeit führt dies dazu, dass die PATH-Variable des Hosts interpoliert wird und nicht der Container

Wird in einer docker-compose.yml-Datei nur eine gefunden?
Wie kann ich es hinzufügen oder ändern?
Danke im Voraus

@logicminds Obwohl ich es nirgendwo dokumentiert finden konnte, fand ich, dass $$ zu einem entkommenen $ interpoliert.

environment:
   PATH: "$$PATH:/home/appuser/.bundler/bin"

@elquimista hat eine Lösung, die ich als nützlich empfunden habe: https://github.com/mhart/alpine-node/issues/48#issuecomment -430902787

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen