Compose: Interpoler les variables d'environnement dans docker-compose.yml

Créé le 30 avr. 2015  ·  109Commentaires  ·  Source: docker/compose

(Je crée un nouveau problème pour cela, car l' ancien a accumulé beaucoup de bagages.)

Il devrait être possible de passer des variables d'environnement à la valeur de n'importe quelle * entrée de configuration dans docker-compose.yml . Beaucoup de gens veulent le faire, c'est bon pour la portabilité et je suis convaincu que cela ne causera pas le chaos.

J'ai quelques comptes.

Variables requises et valeurs par défaut facultatives

Il est utile de pouvoir spécifier qu'une variable _doit_ être présente dans l'environnement, c'est-à-dire que Compose refusera de s'exécuter si ce n'est pas le cas. Cependant, ce sera pénible lorsque vous en avez beaucoup, donc ce devrait être quelque chose que vous activez explicitement, ou il devrait être possible de spécifier une valeur par défaut.

L'implémentation MVP n'a pas besoin d'avoir l'une ou l'autre des fonctionnalités, mais il devrait y avoir un chemin clair pour implémenter les deux d'une manière rétrocompatible.

Syntaxe

Il existe de solides arguments en faveur de la mise en œuvre d'une norme établie, tant qu'elle n'est pas lourde - nos exigences en matière de fonctionnalité sont minimes.

  • L'expansion des paramètres POSIX est OK. Il a quelques fonctionnalités de trop, mais nous pourrions en implémenter un sous-ensemble:

    • ${VARIABLE} - renvoie une chaîne vide si VARIABLE n'est pas défini

    • ${VARIABLE-default} - renvoie default si VARIABLE n'est pas défini

    • ${VARIABLE?} - erreur si VARIABLE n'est pas défini

https://github.com/docker/compose/pull/845 a implémenté une syntaxe ${VARIABLE:default} style Bash, qui est similaire à l'expansion des paramètres POSIX mais légèrement différente.

la mise en oeuvre

La fonction os.path.expandvars Python implémente le cas le plus élémentaire de l'expansion des paramètres POSIX:

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

Cependant, il y a au moins 2 problèmes:

  1. Une variable non définie ne se développe pas en une chaîne vide - au lieu de cela, il n'en résulte aucune expansion:

''

expandvars ('$ {UNSET}')
«$ {UNSET}»
''

  1. Une syntaxe malformée ne se trompe pas - au lieu de cela, elle n'entraîne également aucune expansion:

''

expandvars ('$ {HOME')
«$ {HOME»
''

Jusqu'à présent, https://github.com/docker/compose/pull/845 est le plus proche que nous ayons, mais je me méfie fondamentalement d'une implémentation qui repose sur des expressions régulières. La création de modèles est un travail non trivial, et les gens vont mettre toutes sortes de choses cassées, nous avons donc besoin de quelque chose de robuste, strict et d'erreurs avec des messages utiles. Deux exigences importantes:

  • Si quelqu'un met quelque chose de malformé, Compose ne fonctionnera pas.
  • Il est possible d'échapper à l'un des caractères spéciaux utilisés dans la syntaxe du modèle.

Il existe peut-être déjà de bonnes implémentations Python d'interpolation de variables de type Bash - sinon, créer quelque chose de autonome serait de loin préférable à un gonflement de la base de code Compose.

* En fait, y a-t-il des clés de configuration pour lesquelles nous ne devrions pas autoriser l'interpolation?

kinenhancement kinfeature

Commentaire le plus utile

Mon cas d'utilisation est d'autoriser $PWD dans volumes , afin que chaque développeur de l'équipe puisse cloner un dépôt partout et les chemins sont toujours montés correctement.

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

Tous les 109 commentaires

Jusqu'où voulez-vous aller avec ces normes UNIX établies? (FWIW, ce n'est pas une norme de facto, c'est une norme réelle.)

En tant que personne qui essaie occasionnellement d'utiliser des extensions de paramètres POSIX dans Dockerfiles, si elles étaient prises en charge dans docker-compose.yml, cela ferait de moi un campeur heureux.

@kojiromike Hmm, donc l'expansion des paramètres POSIX est en fait ce que je recherchais, mais en lisant la documentation, il semble que je me souvienne mal de la syntaxe / sémantique.

Edit: J'ai mis à jour mes réflexions sur la syntaxe dans la description.

J'ai suivi l'ancien fil et nous voulions de toute urgence avoir cette fonctionnalité. Finalement, la douleur était trop grande et nous avons créé un script bahs de préprocesseur yaml pour substituer des variables dans le style POSIX. cela a bien fonctionné mais nous avons finalement arrêté de l'utiliser, car il avait un problème. Vous devez d'abord exécuter le préprocesseur et définir tous les paramètres avant d'obtenir la solution finale. Nous utilisons maintenant la fonction docker yaml extend. Parce que cela nous permet de vérifier la configuration réelle et de l'exécuter simplement sur la cible. Nous savons mieux ce qui va se passer.

Même si j'étais un partisan des variables de passage de docker-compose, je n'en suis plus si sûr.

En tant que solution idéale, je préférerais que docker se prolonge correctement. Dans un sens, ce serait une solution qui convient aux deux. Alors, qu'est-ce qui est cassé dans le docker? C'est essentiellement le fait que vous devez écrire toutes les entrées dans le fichier hérité. Il ne s'agit pas d'une fusion dans laquelle vous n'entrez que ce que vous souhaitez remplacer.

Regardez l'exemple réel et comment il est verbeux. Il n'y a que deux lignes qui comptent.

#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

Donc, ma recommandation fixe docker étend et rend moins verbeux. Vous n'avez même pas besoin d'écrire autant de code car YAML fournit toutes les fonctionnalités dont vous avez besoin. Si vous vous en tenez à YAML standard, le fichier pourrait être analysé ou créé par d'autres outils et interfaces utilisateur.

Jetez un œil aux "ancres de nœuds" YAML et à la "fusion de fichiers" YAML, cela pourrait être la solution parfaite.

Pour info: cette discussion continue maintenant sur # 1380

@ Vad1mo Je suis d'accord que extends est insuffisant dans votre cas. Il y a beaucoup de choses que nous pouvons faire pour améliorer cette expérience - pourriez-vous ouvrir un autre numéro pour cela, afin que nous ne soyons pas distraits ici?

Bien sûr! Je voulais juste souligner que cela pourrait être une alternative simple et élégante.
Si composer extend vous permet de passer à moitié trop de variables, alors un compose-extend amélioré rendra le passage de variables obsolète. Avoir moins de concepts à comprendre rend plus facile pour l'utilisateur.

Mon cas d'utilisation est d'autoriser $PWD dans volumes , afin que chaque développeur de l'équipe puisse cloner un dépôt partout et les chemins sont toujours montés correctement.

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

@mattes Je pense que c'est déjà pris en charge, je pense que .:/app est également

@aanand En tant que PoC, j'ai fait un sale hackup de POSIX PE en Python . Pour les samedis.

@kojiromike Ça a l'air génial. Faites-moi savoir si vous prévoyez de continuer.

@aanand j'ai l'intention de le faire, mais il y a certainement quelques bugs en ce moment (et je pense que cela a peut-être été une mauvaise idée d'utiliser shlex ). Les rapports de bogues et les RP sont bien entendu les bienvenus.

@dnephin que diriez-vous de $HOME / ~ ?

@nafg Les deux sont pris en charge pour le chemin d'hôte d'un volume

@dnephin intéressant, b / c en quelque sorte, je me suis retrouvé avec un répertoire nommé '$ HOME' ...

@aanand Comme la VARIABLE: default }", avec global_extends (ou "import") cela deviendrait assez puissant.

Q: Cela permettrait-il de spécifier le numéro de port exposé à l'hôte? comme - "$ {WEB_ PORT: 80 }: 80"?
Le cas d'utilisation est de pouvoir facilement lancer plusieurs instances d'une application sur la même machine / cluster, généralement en écoutant différents ports ou attribués à différents noms de domaine locaux.

Oui, vous seriez capable de le faire.

Je voudrais utiliser vars dans les volumes avec docker-compose scale my_app=3 . J'ai ceci 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

Et je veux pouvoir utiliser scale pour les agents et utiliser des volumes dynamiques pour qu'ils conservent les données entre les lancements, par exemple:

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

J'espère qu'il serait également possible d'interpoler des variables dans le cadre du nom de l'image
Nous utilisons https://github.com/openshift/source-to-image pour créer un conteneur local sur CI pour chaque branche, puis exécutons des tests dessus à l'aide de docker-compose.
Exécuter des tests avec une image dynamique est assez compliqué avec docker-compose et nécessite un rendu de modèle manuel.: -1:

Mais vous pouvez définir COMPOSE_PROJECT_NAME pour contrôler le préfixe par exécution pour pouvoir le faire déjà, n'est-ce pas? Si c'est le cas, pas besoin d'avoir une logique complexe et des fichiers yml illisibles autour des noms.

@andrerom ne suit pas. Selon la documentation qui contrôle les Sets the project name, which is prepended to the name of every container started by Compose pendant que nous essayons de définir une propriété d'image à la place:

web:
  image: <I_AM_DYNAMIC>

ah, mon erreur.

Je pensais que tu voulais dire

<I_AM_DYNAMIC>:
  image: nginx

Une référence d'image dynamique (et de construction) aurait en effet beaucoup de sens. Par exemple, basculer entre des conteneurs de base de débogage et non de débogage pour votre langage de programmation, par exemple, serait un bon cas d'utilisation pour cela.

Cas d'utilisation supplémentaire _ (qui pourrait être ce que @ Maxim-Filimonov a en tête) _: Être capable de remplacer la balise à utiliser d'une image, afin que vous puissiez utiliser: dernier par défaut, mais changez pour tester facilement autre chose sans changer de yml file _ (nécessaire pour les cas d'utilisation de CI essentiellement) _.

@andrerom c'est exactement notre cas d'utilisation: +1:

Cela fonctionnera-t-il également pour des choses comme ??

web:
  environment:
    - FOO=${whoami}

@ k0377 Je ne pense pas qu'ils le feront, car c'est vraiment quelque chose qui est géré par le shell, mais vous pouvez ajouter le résultat dans une variable d'environnement et l'utiliser.

Dans ce cas particulier, la variable d'environnement $USER vous donnera probablement la même chose.

@aanand Pourquoi ne pas utiliser l'un des moteurs de modèles existants déjà présents? Jinja2 est là et fonctionne très bien.

Comme mentionné précédemment, implémenter notre propre modèle est une tâche non triviale (et les expressions rationnelles ne sont pas si cool), de sorte que nous devrions utiliser un modèle déjà existant, qui s'est avéré solide.

Alternativement, nous pouvons utiliser des ancors et références YAML https://gist.github.com/bowsersenior/979804

Mais alors nous sommes limités sur l'utilisation des variables (injecter le nom de la variable au milieu du contenu).

+1 pour Jinja2: il s'adapterait certainement au moule et l'utilisera pour
exactement ce cas d'utilisation (création de modèles dans des fichiers yml)

Le mar 26 mai 2015 à 13 h 25, tonnzor [email protected] a écrit:

@aanand https://github.com/aanand Pourquoi ne pas utiliser l'un des modèles existants
moteurs déjà présents? Jinja2 est là et fonctionne très bien.

Comme mentionné précédemment, la mise en œuvre de notre propre modèle est une tâche non triviale
(et les regexps ne sont pas si cool) de sorte que nous devrions utiliser une déjà existante,
cela s'est avéré solide.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105493447.

Jinja2 fait un _lot_ plus que ce dont nous avons besoin:

  • conditionnels
  • boucle
  • extension / héritage
  • commentaires
  • filtres

Nous n'ajoutons rien de tout cela à Compose. Si Jinja2 peut être configuré pour simplement interpoler des variables, alors il pourrait être un candidat.

En fait, la boucle peut être intéressante.

Supposons que vous ayez une liste de clients pour lesquels vous souhaitez démarrer des conteneurs
où vous mettez certaines variables spécifiques au client dans l'environnement.

L'extension / l'héritage peut être intéressant pour améliorer le
mécanisme d'extension rudimentaire.

Les filtres peuvent être utiles pour faire quelque chose avec des variables existantes.

Le mar 26 mai 2015 à 13 h 56, Aanand Prasad [email protected]
a écrit:

Jinja2 fait un _lot_ plus que ce dont nous avons besoin:

  • conditionnels
  • boucle
  • extension / héritage
  • commentaires
  • filtres

Nous n'ajoutons rien de tout cela à Compose. Si Jinja2 peut être configuré
pour simplement interpoler des variables, alors cela pourrait être un candidat.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105498909.

Elles _pourraient_ être des fonctionnalités intéressantes, mais elles sont beaucoup plus complexes que je ne suis à l'aise pour présenter à la fois Compose et le format de fichier, et nous les lierions à un langage de modélisation spécifique avec (pour autant que je sache) une seule implémentation et aucune spécification. Ce n'est tout simplement pas faisable.

@aanand Quelques notes ici:

  1. Jinja2 est solide et il faut quelques minutes pour faire le prétraitement de YAML avec:

à partir du modèle d'importation jinja2
template = Template ('Bonjour {{name}}!')
template.render (nom = "Aanand")
Bonjour Aanand!

Si vous voulez plus de sécurité, vous pouvez utiliser un bac à sable immuable:

à partir de jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Bonjour {{name}}!')
template.render (nom = "Aanand")
Bonjour Aanand!

Dans notre cas, ce serait:

importer le système d'exploitation
à partir de jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Bonjour {{name}}!')
template.render (** os.environ)

  1. Ne voulons-nous pas de filtres? Avec le filtre, vous pouvez définir facilement la valeur par défaut ({{value | default ("default")}})
  2. Avons-nous vraiment besoin de nous soucier des utilisateurs qui utilisent des fonctionnalités étendues de Jinja pour visser le fichier YAML? De la même manière, l'utilisateur peut produire manuellement un fichier YAML invalide. Je pense que nous devrions garder les choses simples - essayez de traiter le modèle Jinja donné et de renvoyer une erreur s'il y avait une erreur ou si le YAML produit n'est pas valide (comme vous le faites maintenant).
  3. Si vous ne voyez pas Jinja2 comme solution, ce serait bien d'utiliser au moins {{variable}} comme syntaxe.
  4. Django utilise regexp pour analyser et générer un modèle. Il est de qualité production pendant longtemps et vit bien avec.

importer le système d'exploitation
importer re
template = "Bonjour {{name}}!"
re.sub ("{{\ s _ ([a-zA-Z0-9 _] +?) \ s_}}", lambda m: os.environ.get (m.group (1), ''), modèle)

Dans tous les cas, nous devons faire fonctionner cette fonctionnalité, quelle que soit la solution que nous prenons.

Je suis +1 sur l'utilisation d'une solution de modèle générique si les modèles sont pris en compte. Par exemple http://mustache.github.io , qui est disponible dans de nombreuses langues. Ceci n'est qu'un exemple, d'autres moteurs de modèles peuvent être considérés de la même manière

@aan et je comprends tout à fait votre point. J'aime aussi la simplicité et
succinct de la composition DSL.

Peut-être que cela devrait être fait en tant que projet externe, dit méta-compositeur. Il
prend un compose.tpl.yml et un variables.yml, crée un docker-compose.yml
et c'est parti.
Comme @tonnzor l'a montré, t pourrait être fait avec un petit morceau de code python.

Cela fournirait des modèles puissants à ceux qui en ont besoin sans
introduire de la complexité pour des tâches simples.

Le mar 26 mai 2015 à 16:52, Sebastiaan van Stijn <
[email protected]> a écrit:

Je suis +1 sur l'utilisation d'une solution de création de modèles _generic_ si les modèles sont
pris en considération. Par exemple, http://mustache.github.io , qui est disponible dans de nombreux
langues. Ceci n'est qu'un exemple, d'autres moteurs de modèles peuvent être
considéré également

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Hmm… Il en va de même pour la proposition d'utiliser un langage de création de modèles dans compose.yml (qui est un langage descriptif pour composer des conteneurs Docker), pour des choses comme command et entrypoint , qui acceptent déjà les deux exec et sh -c valeurs de style? Cela pourrait être déroutant, car après le rendu du modèle, la commande shell résultante serait toujours vraisemblablement interprétée, donc si une variable se développait jusqu'à * elle serait encore étendue globalement. Échapper à des séquences dans une langue ou une autre devient délicat lorsque vous avez autant de couches d'interprétation fall-through.

@kojiromike Je ne suis pas sûr qu'un moteur de s'il doit être utilisé! mieux utiliser quelque chose de bien connu. La question fondamentale est; devrait docker-compose écrire la substitution à partir de zéro, ou utiliser quelque chose d'existant.

Le mar 26 mai 2015, 11 h 02 Christoph Witzany [email protected]
a écrit:

@aan et je comprends tout à fait votre point. J'aime aussi la simplicité et
succinct de la composition DSL.

Peut-être que cela devrait être fait en tant que projet externe, dit méta-compositeur. Il
prend un compose.tpl.yml et un variables.yml, crée un docker-compose.yml
et c'est parti.

Vous pouvez le faire aujourd'hui sans nouveau projet. Je suis sûr que Jinja peut être
invoqué d'une manière ou d'une autre à partir de la ligne de commande. Personnellement, j'utilise juste l'envsubst
commander.

Ce qui serait vraiment utile, c'est que compose puisse lire le fichier depuis stdin.
Cela éliminerait le besoin d'un fichier intermédiaire.

Comme @tonnzor l'a montré, t pourrait être fait avec un petit morceau de code python.

Cela fournirait des modèles puissants à ceux qui en ont besoin sans
introduire de la complexité pour des tâches simples.

Le mar 26 mai 2015 à 16:52, Sebastiaan van Stijn <
[email protected]> a écrit:

Je suis +1 sur l'utilisation d'une solution de création de modèles _generic_ si les modèles sont
pris en considération. Par exemple, http://mustache.github.io , qui est disponible dans de nombreux
langues. Ceci n'est qu'un exemple, d'autres moteurs de modèles peuvent être
considéré également

Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Répondez directement à cet e-mail ou affichez-le sur GitHub
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 pour lire le fichier depuis stdin. Je n'ai aucun problème avec l'utilisation d'une solution de modèle externe, mais ne pas avoir de fichiers intermédiaires serait bien.

Cela semble être une excellente première étape et une caractéristique commune à de nombreux outils cli. Faisons cela

: +1:

Donc par exemple

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

wfm. : +1:

Je viens de remarquer que docker / distribution gère les valeurs de remplacement dans le fichier yml via des variables d'environnement, mais en utilisant une approche différente https://github.com/docker/distribution/blob/master/docs/configuration.md#override -configuration-options

^^ @aanand

@thaJeztah qui fonctionnerait aussi pour nous. Nous pouvons utiliser des variables d'environnement pour remplacer les commandes puis

DOCKER_COMPOSE_IMAGE_NAME='my_image:is_dynamic'

Approche intéressante, mais je ne suis pas fan - noms de variables d'environnement verbeux, beaucoup de duplication si vous voulez utiliser une valeur à plusieurs endroits, tout est implicite, pas d'interpolation dans les chaînes.

@aanand n'a pas vraiment vendu cette approche non plus, mais a voulu la pointer car c'est un autre projet au sein de l'organisation "Docker".

Je viens de trébucher sur https://github.com/kelseyhightower/confd, ce qui pourrait être intéressant. Il utilise http://golang.org/pkg/text/template/#pkg -overview

@olalonde malheureusement, docker-compose est écrit en Python, donc Go-templates ne fonctionnera pas.

@aanand Je suis +20 sur votre proposition originale, avec le tweak que même les images et en particulier les tags devraient pouvoir être injectés. Allez-y, cela nous épargnerait à tous beaucoup de wrappers et une gestion de configuration inutile;)

J'ai écrit un petit paquet python qui m'aide avec ça. Le plan est de canaliser toutes les commandes vers docker compose afin que vous puissiez l'utiliser de manière équivalente.
Découvrez-le sur https://github.com/webcrofting/meta-compose/

meta-compose est vraiment sympa. Il devrait être intégré à docker-compose!

Big +1 ici - Je ne suis pas enthousiasmé par le prétraitement des modèles, mais extraire les variables d'environnement d'une manière ou d'une autre serait génial. L'expansion POSIX est probablement plus propre que Jinja2, mais dans les deux cas, c'est bien.

Big +1 d'ici aussi. Mon cas d'utilisation est davantage l'ajout de la prise en charge de l'identifiant publicitaire dynamique pour le conteneur kafka, ce qui est vital pour les producteurs de données (qui pourraient être d'autres conteneurs).

Je suis également enthousiasmé par cette fonctionnalité.

L'expansion POSIX est probablement plus propre que Jinja2, mais dans les deux cas, c'est bien.

Je pense qu'un autre argument en faveur de l'expansion POSIX est qu'elle est sans logique. Jinja2 prend en charge un certain degré de logique conditionnelle / boucle (comme le font la plupart des moteurs de création de modèles, même ceux qui prétendent être "sans logique"). Mélanger la logique de modélisation et YAML est assez étrange dans mon expérience. Quelqu'un peut-il penser à un cas d'utilisation d'une telle logique? Sinon, il peut être préférable d'éviter spécifiquement le support pour le moment.

Ce serait bien d'avoir une réponse claire des développeurs sur cette fonctionnalité. En lisant divers problèmes et relations publiques, il n'est pas clair si vous voulez vraiment le mettre en œuvre ou non.

Si oui, avec quel genre de mécanisme? Sinon, les gens pourraient commencer à créer des outils tiers pour gérer la fonctionnalité.

Je vous remercie !

Ok, je viens de voir https://github.com/docker/compose/pull/76. Je suppose que la réponse est là ...

J'ai parcouru quelques cycles sur les problèmes / PR liés.

AFAIK, la communauté nginx a refusé d'adopter un moteur de modèle pour les fichiers de configuration, même pour une simple substitution de variable. Pourquoi? Peut-être qu'ils choisissent toujours un moteur de template idéal: smile :. Résultat? Douleur (relativement)!

@hadim

En lisant divers problèmes et relations publiques, il n'est pas clair si vous voulez vraiment le mettre en œuvre ou non.

Ce problème était censé fournir la réponse définitive à cette question, donc je suis désolé de ne pas avoir été clair: oui, nous voulons l'implémenter, et avec une syntaxe de style POSIX.

merci @aanand !

Merci, @aanand.

+1 pour moi. Je dois passer --dns = (adresse du pont docker0), et j'en ai besoin pour fonctionner si cela change jamais dans les futures versions de docker, donc une variable d'environnement et / ou un shell est parfait. meta-compose ne fonctionne pas pour moi, car il devrait prendre en charge DOCKER_HOST distant et par exemple via docker-swarm, pas seulement localement.

: +1: Ce serait très sympa. Actuellement, soit je finis par générer le fichier .yml via un autre script, soit je n'utilise tout simplement pas docker-compose et manuellement - les dockers de liaison.

:pouces vers le haut:

Je pense que l'interpolation des variables d'environnement de base serait très utile pour des choses simples.

Quelques cas d'utilisation simples:

  • Être capable de spécifier dynamiquement la balise d'une image à extraire d'un référentiel distant.
  • Être capable de définir le mappage de port pour un conteneur.

Des outils comme Ansible font déjà très bien la création de modèles, je ne suis donc pas sûr qu'un moteur de modèle complet soit nécessaire. Mais ne pas pouvoir avoir de contenu dynamique dans le fichier comose.yml est très limitant.

En ce qui concerne le PR # 1488 fusionné, je suis particulièrement intéressé par le piping d'un fichier de configuration vers docker-compose . Je ne comprends pas pourquoi docker-compose ne peut pas récupérer à partir d'un processus de nœud.

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();

Des exemples sur la façon de canaliser des données à partir de Node.js?

Une autre chose que j'ai trouvée est que docker-compose 1.4.0-RC1 envoie des messages apparemment normaux comme Starting... ou Attaching... au stderr au lieu de stdout .

@kadishmal Pourriez-vous ouvrir des numéros séparés pour ceux-ci s'il vous plaît?

Une autre syntaxe / implémentation candidate: le modèle de chaîne de Python, tel que spécifié dans PEP 0292 et implémenté dans string.Template .

C'est très similaire à l'expansion des paramètres POSIX:

  • $foo développe jusqu'à la valeur de foo
  • ${foo} augmente jusqu'à la valeur de foo
  • $ , ${ , $} , ${} , ${foo , $ {foo} , ${ foo} , ${foo } sont des erreurs

Désavantages:

  • Aucune valeur par défaut ou syntaxe de «valeur requise». Pourtant, nous pourrions décider plus tard si nous voulons que ceux-ci méritent d'écrire notre propre code de modèle.
  • Les messages d'erreur n'exposent aucune information lisible par machine sur l'emplacement de l'erreur de syntaxe (sans effectuer de correspondance regex sur la chaîne d'erreur, c'est-à-dire).
  • La syntaxe d'échappement diffère de POSIX: $$ au lieu de \$ .

Cela pourrait en fait être une bénédiction déguisée: YAML n'aime pas \$ , et vous oblige à double-échapper. Je ne pense pas que dire aux gens de taper \\$ juste pour obtenir un signe dollar va voler.

J'ai ajouté une implémentation dans # 1765.

+1

Je ne sais pas si c'est le bon endroit pour cela, ou si je devrais faire un nouveau numéro.

Je pense que la priorité env devrait être l'inverse, c'est-à-dire qu'une variable du shell qui invoque docker-compose devrait remplacer toute variable dans docker-compose.yml, qui à son tour devrait remplacer toute variable définie par le conteneur.

Voici ce qui se passe actuellement lorsque je l'essaye:

docker-compose.yml:

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

puis exécutez-le avec la commande env :

docker-compose run test env | grep FOO

donne FOO="from compose" , comme prévu. Mais alors:

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

donne aussi FOO="from compose" , mais ici je m'attendais à FOO="from shell" .

Certaines personnes peuvent encore avoir besoin d'une interpolation de variable pour d'autres cas d'utilisation, mais changer cela satisferait le cas "par défaut" - effectivement, la définition / valeur environment: dans docker-compose.yml est la valeur par défaut, et elle peut être remplacée au moment de l'exécution si nécessaire, sans avoir besoin de syntaxe YAML supplémentaire.

@fazy vous n'avez pas pris en compte que la commande env été exécutée dans le conteneur isolé test dans lequel la FOO est from compose (juste comme il se doit et comme il a été configuré dans un fichier docker-compose ). Mais en dehors de ce conteneur, si docker-compose process avait une sorte de fonction d'impression pour la variable d'environnement que vous avez configurée avant la commande, il aurait imprimé 'à partir du shell' car c'est la valeur de l'hôte (ainsi que pour le processus docker-compose ) sur lequel vous l'exécutez. Peut-être que vous vous attendiez à ce que la FOO soit de from shell dans ce cas, mais personnellement, je serais assez surpris si c'était le cas. (J'espère que malgré mon anglais, vous comprendrez mon point).

@smileart merci, je pense que je vois ce que vous dites.

Cependant, le conteneur test n'est pas complètement isolé, il obtient son environnement de docker-compose (ou du moins, docker-compose est capable de définir des variables d'environnement dans le conteneur lancé), et docker-compose lui-même peut voir la variable d'environnement "externe".

Vous pouvez voir avec ce docker-compose.yml:

test:
    image: ubuntu
    environment:
        - FOO

Puis la commande:

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

donne en effet le résultat "from shell".

Ma question porte donc sur la préséance. En spécifiant uniquement le nom de la variable ici, - FOO , je peux injecter la variable de l'extérieur. Mais si je spécifie - FOO=something _et_ injecter une variable de l'extérieur, laquelle devrait avoir la priorité? IMHO la variable spécifiée sur la ligne de commande doit avoir la priorité sur le fichier de configuration.

@fazy Oh, désolé, je n'ai pas essayé FOO="from shell" docker-compose run test env | grep FOO sans spécifier sa valeur dans le docker-compose.yml et je ne savais pas que cela nous donne la FOO hôte. Donc, ce ne serait pas juste que ce soit déjà étrange pour moi: smiley: je pensais que la configuration d'une variable d'environnement avant docker-compose influencerait docker-compose et docker-compose UNIQUEMENT sans la jeter dans le récipient. Maintenant je vois ce que tu voulais dire.

Je viens de tomber sur l'inconvénient d'échapper à $ mentionné dans https://github.com/docker/compose/issues/1377#issuecomment -124571722. D'abord j'ai juste fait FOO=ba$e puis FOO='ba$e' (en oubliant que c'est pris "nu"), puis FOO=ba\$e , puis FOO=ba\\$e , puis j'ai abandonné et suis allé à la documentation, juste pour être surpris de découvrir que " $ est le caractère d'échappement pour $ ". Pour moi, ce n'était pas particulièrement "la moindre surprise".

Cependant, je ne sais pas quelle serait la bonne solution.

@ ct-clearhaus Compose n'est pas le seul programme qui utilise $ pour échapper $ . Vous le trouverez également dans les makefiles. Donc, pour certaines personnes, cet idiome est assez familier.

J'adore l'implémentation de substitution de variable existante. Cependant, je pourrais vraiment utiliser la possibilité de définir une valeur par défaut, conformément à la proposition originale de @aanand . Je pense que la syntaxe POSIX est parfaite:

${ENV-default}

Mon utilisation spécifique est que je souhaite pouvoir spécifier le port hôte sur lequel le service s'exécute:

PORT=8123 docker-compose up

En ajoutant ceci à mon docker-compose.yml :

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

Cette fonctionnalité est-elle toujours prévue et en préparation?

J'ai essayé de résoudre mon problème avec les extensions , mais cela est devenu assez compliqué. Non seulement ai-je dû dupliquer presque tous mes docker-compose.yml juste pour changer un paramètre, mais il n'y a pas non plus moyen de _changer_ un paramètre de port exposé, vous ne pouvez que add to la liste des ports exposés, ce qui n'est pas idéal pour moi.

Pourquoi docker-compose n'échoue-t-il pas lorsque les variables d'environnement ne sont pas définies? Il enregistre simplement un avertissement et continue. Le retour et l'erreur ne seraient pas une meilleure approche ...
WARNING: The FOO variable is not set. Defaulting to a blank string.

+1 pour la syntaxe POSIX pour la déclaration des valeurs par défaut

Il me manque peut-être quelque chose d'évident, mais j'aimerais pouvoir utiliser des variables d'environnement à partir d'un env_file pour définir la valeur d'une variable d'environnement, par exemple:

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}

Cela pourrait-il être accompli d'une autre manière? Je ne veux pas avoir un fichier de modèle yaml qui doit être acheminé via envsubst.

Pourquoi ne pas simplement mettre cette valeur directement dans le env_file comme vous le souhaitez?

2636 prendra en charge un fichier env pour les valeurs par défaut

Cela signifierait avoir une variable qui doit avoir la même valeur à deux endroits, ce qui facilite les choses si vous n'avez besoin d'en changer qu'un. # 2636 semble prometteur.

Nous avons désespérément besoin d'un mécanisme pour prendre en charge les variables par défaut maintenant, car les limitations existantes nous obligent à utiliser des scripts wrapper pour aider docker-compose. J'ai besoin de trucs comme NODE_ENV=${NODE_ENV:-dev} pour travailler, et pour plus de commodité, ce serait bien d'avoir SOME_NUMBER=$((96*60)) pour travailler. Était-ce prévu pour une prochaine version?

+1 pour les valeurs par défaut

+1 pour les valeurs par défaut. cela devient critique pour nous.

J'accepte @ darkn3rd - J'ai besoin d'obtenir un identifiant d'utilisateur et un identifiant de groupe d'utilisateurs pour les configurer dans le conteneur. Le seul moyen que j'ai trouvé est de forcer mon équipe à exporter 2 vars ... ou d'utiliser un makefile que j'ai créé pour les exporter.

Si seulement je peux faire:

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

qui résoudra tous mes problèmes

@mgor On dirait que vous pourriez simplement le passer par envsubst ?

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

devrait le faire (sans polluer l'environnement persistant), je pense.

@OJFord @mgor Aucune intention de détourner le thread mais j'ai construit quelques outils CLI pour avoir un flux de travail plus propre; envset et slv .

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

envset chargera les variables d'un fichier env dans la session shell actuelle, slv remplacera le modèle en utilisant des variables d'environnement.

Je suis d'accord @OJFord mais ce n'est pas ce dont j'ai besoin ...
Permettez-moi de préciser: nous sommes une équipe de 40 développeurs qui utilise différentes piles de docker-compose. Nous utilisons git pour obtenir du code.

Si je leur demande de modifier docker-compose.yml qui est livré par notre git, donc je suis sûr que quelqu'un va pousser un fichier docker-compose.yml modifié ... Faites-moi confiance, ce sera le cas.

Je peux "générer un fichier de composition de base" qui est ignoré par git et étendu par docker-compose.yml, mais pour le générer, je devrai leur donner un Makefile ou un bashscript ... Le jour viendra où un "base docker file "une modification sera nécessaire, et l'équipe ne sera pas consciente qu'elle devra réexécuter la génération.

Idem pour un fichier "env", c'est très sympa, mais il ne fonctionne pas avec "build" et je dois demander à mon équipe de générer ce fichier.

Vraiment, si docker-compose peut obtenir des valeurs de bash (ou de toute autre solution qui retourne autre chose qu'une var ENV) dans le fichier yaml, cela résoudra beaucoup de besoins.

Mon exemple dans ma commande précédente est parfait: j'ai besoin d'obtenir l'ID utilisateur et le gid et ces valeurs ne sont pas définies par ENV vars. Je dois donc demander à mon équipe d'écrire leurs identifiants dans un fichier .env ... Simple pour moi et vous, pas pour tous.

Pour préciser: je dois donner un fichier docker-compose qui ne doit pas être modifié par l'équipe, car il se trouve sur un référentiel git.

Cette pull-request est un exemple simple qui fonctionne pour moi. Peut-être pouvez-vous m'aider à faire mieux.

J'ai essayé avec les directives d'environnement et d'utilisateur du fichier docker-compose.yml. Fonctionne bien pour le moment.

La valeur par défaut devrait être là ... Très utile ... Les développeurs et les OPS utilisent soit les journaux docker, soit syslog ... Donc, ils doivent généralement créer le LOG_FORMAT par défaut indiqué ci-dessous ... Nous pourrions simplement avoir la valeur par défaut et ne l'utilisez que lors du passage à syslog ...

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"

Quand sera-ce disponible? Je suis sur Compose 1.7.0 et ce n'est toujours pas là :(

Merci de nous indiquer les valeurs par défaut!

@marcellodesales : Vous pouvez peut-être profiter de l'utilisation d'un fichier docker-compose.override.yml d'une manière ou d'une autre. Vérifiez cette fonctionnalité.

Également +1 sur les vars env. C'est notre principal problème avec docker-compose de nos jours.

J'insisterais sur mon PR # 3367 pour pouvoir obtenir certaines valeurs de l'hôte. :)

@pataquets Je ne pense pas que je veux créer encore un autre fichier de remplacement ... notre fichier base.yml , comme indiqué ci-dessus, montre tous les éléments pris en charge en termes de pilote de journalisation, etc ... Je veux juste changer et ont des valeurs par défaut. Je pense que nous aurions besoin de maintenir encore plus de fichiers yml. Mais je garderai cela à l'esprit au cas où.

+1

+1

+1

+1

Un avis sur l'utilisation des variables d'environnement dans docker-compose?

+1

+1

Pour info: les variables d'environnement pour les travaux docker-compose à partir de la version 1.7.0. Vous pouvez également définir les variables par défaut de docker-compose dans .env dans le même répertoire que votre fichier racine docker-compose.yml . Cela ne doit pas être confondu avec les fichiers d'environnement du moteur docker, car c'est une chose différente.

Existe-t-il un moyen de définir le nom du service en tant que variable?

Au lieu d'écrire ceci

services:
   site_db:
     image: mysql:5.7

Nous pourrions écrire

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

Mon objectif est de conserver le même docker-compose.yml sur plusieurs sites et de ne modifier que le fichier .env . Pour le moment, je dois encore modifier le nom du conteneur car j'exécute plusieurs applications sur le même hôte. Et j'aimerais que chaque service ait son propre nom pour plus de clarté.

@LouWii vous pouvez utiliser

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

ou (format de fichier de composition 2.1 et plus)

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

Mais pourquoi ne pas définir le nom du projet? Le nom du projet est _intended_ pour cela, car il préfixe / namespaces les noms de conteneurs qui sont créés pour éviter tout conflit avec d'autres projets sur le même hôte. Voir https://docs.docker.com/compose/reference/envvars/#/composeprojectname

@thaJeztah Merci! J'apprends toujours comment Docker et docker composent fonctionnent. Définir le nom du projet semble être une meilleure option, cela a tout son sens dans mon utilisation.

Existe-t-il un moyen de script dans les accolades interpolées? Par exemple ${HOST_PORT + 1} .

Vous pouvez diriger le fichier via Jinja ou quelque chose comme ça ...

Le mar 24 janvier 2017 05 h 36 Sam A. Horvath-Hunt [email protected]
a écrit:

Existe-t-il un moyen de script dans les accolades interpolées? Par exemple $ {HOST_PORT

  • 1}.

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/docker/compose/issues/1377#issuecomment-274767368 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAGAUN5ZrU39dnVVVASwIHr5mGqJFxh3ks5rVdRIgaJpZM4EMysO
.

Suis-je capable d'échapper à $ ?

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

Actuellement, cela entraîne l'interpolation de la variable PATH de l'hôte et non du conteneur

un seul fichier docker-compose.yml est-il trouvé?
comment puis-je l'ajouter ou le modifier?
Merci d'avance

@logicminds bien que je ne puisse pas le trouver documenté nulle part, j'ai trouvé $$ interpole vers un $ échappé.

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

@elquimista a une solution que j'ai trouvée utile https://github.com/mhart/alpine-node/issues/48#issuecomment -430902787

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

dimsav picture dimsav  ·  3Commentaires

29e7e280-0d1c-4bba-98fe-f7cd3ca7500a picture 29e7e280-0d1c-4bba-98fe-f7cd3ca7500a  ·  3Commentaires

dazorni picture dazorni  ·  3Commentaires

DhairyashilBhosale picture DhairyashilBhosale  ·  3Commentaires

bergtwvd picture bergtwvd  ·  3Commentaires