Compose: Interpolar variables de entorno en docker-compose.yml

Creado en 30 abr. 2015  ·  109Comentarios  ·  Fuente: docker/compose

(Estoy creando un nuevo problema para esto, ya que el anterior ha acumulado bastante equipaje).

Debería ser posible pasar variables de entorno al valor de cualquier * entrada de configuración en docker-compose.yml . Mucha gente quiere hacerlo, es bueno para la portabilidad y estoy satisfecho de que no causará caos.

Tengo algunos cálculos.

Variables necesarias y valores predeterminados opcionales

Es útil poder especificar que una variable que _debe_ estar presente en el entorno, es decir, que Compose se negará a ejecutarse si no lo está. Sin embargo, esto será un problema cuando tenga muchos, por lo que debería ser algo que habilite explícitamente o debería ser posible especificar un valor predeterminado.

La implementación de MVP no necesita tener ninguna de las características, pero debe haber un camino claro para implementar ambas de una manera compatible con versiones anteriores.

Sintaxis

Existe un caso sólido para implementar un estándar establecido, siempre que no sea de peso pesado: nuestros requisitos de funcionalidad son mínimos.

  • La expansión del parámetro POSIX está bien. Tiene demasiadas características, pero podríamos implementar un subconjunto de ellas:

    • ${VARIABLE} - genera una cadena vacía si VARIABLE está configurado

    • ${VARIABLE-default} - genera default si VARIABLE está configurado

    • ${VARIABLE?} - errores si VARIABLE está configurado

https://github.com/docker/compose/pull/845 implementó una sintaxis ${VARIABLE:default} estilo Bash, que es similar a la expansión de parámetros POSIX pero ligeramente diferente.

Implementación

La función os.path.expandvars Python implementa el caso más básico de expansión de parámetros POSIX:

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

Sin embargo, tiene al menos 2 problemas:

  1. Una variable no configurada no se expande a una cadena vacía, sino que no produce expansión:

''

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

  1. La sintaxis mal formada no genera errores; en cambio, tampoco resulta en ninguna expansión:

''

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

Hasta ahora, https://github.com/docker/compose/pull/845 es lo más cercano que tenemos, pero desconfío fundamentalmente de una implementación que se basa en expresiones regulares. La creación de plantillas no es un trabajo trivial, y la gente va a colocar todo tipo de material roto, por lo que necesitamos algo que sea sólido, estricto y que contenga errores con mensajes útiles. Dos requisitos importantes:

  • Si alguien introduce algo con formato incorrecto, Compose no se ejecutará.
  • Es posible escapar de cualquiera de los caracteres especiales utilizados en la sintaxis de la plantilla.

Es posible que ya existan buenas implementaciones de Python de interpolación de variables similares a Bash; de lo contrario, crear algo independiente sería mucho mejor que sobrecargar la base de código de Compose.

* En realidad, ¿existen claves de configuración para las que _no deberíamos_ permitir la interpolación?

kinenhancement kinfeature

Comentario más útil

Mi caso de uso es permitir $PWD en volumes , por lo que cada desarrollador del equipo puede clonar un repositorio en cualquier lugar y las rutas aún se montan correctamente.

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

Todos 109 comentarios

¿Qué tan lejos quiere llegar con estos estándares UNIX establecidos? (FWIW, no es un estándar de facto, es un estándar real).

Como alguien que ocasionalmente intenta accidentalmente usar expansiones de parámetros POSIX en Dockerfiles, si fueran compatibles con docker-compose.yml, me haría un campista feliz.

@kojiromike Hmm, entonces la expansión del parámetro POSIX es en realidad lo que estaba buscando, pero al leer los documentos, parece que me olvidé de la sintaxis / semántica.

Editar: He actualizado mis pensamientos sobre la sintaxis en la descripción.

He estado siguiendo el hilo anterior y queríamos tener esta función con urgencia. Finalmente, el dolor fue demasiado grande y creamos un script bahs de preprocesador yaml para sustituir variables en estilo POSIX. Funcionó bien, pero finalmente dejamos de usarlo porque tenía un problema. Primero debe ejecutar el preprocesador y configurar todos los parámetros antes de obtener la solución final. Ahora estamos usando la función de extensión yaml de la ventana acoplable. Porque nos permite verificar la configuración real y simplemente ejecutarla en el objetivo. Sabemos mejor lo que va a pasar.

A pesar de que era partidario de las variables de paso de composición de docker, ahora no estoy tan seguro.

Como solución ideal, preferiría ver las extensiones de docker bien hechas. En cierto sentido, esa sería una solución que se ajusta a ambos. Entonces, ¿qué está roto en Docker? Básicamente es el hecho de que tienes que escribir todas las entradas en el archivo heredado. No es una combinación en la que ingresa solo lo que desea anular.

Mire el ejemplo real y cuán detallado es. Solo hay dos líneas que importan.

#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

Entonces, mi recomendación para corregir la ventana acoplable se extiende y la hace menos detallada. Ni siquiera tiene que escribir tanto código ya que YAML proporciona toda la funcionalidad que necesita. Si se apega al YAML estándar, el archivo podría ser analizado o creado por otras herramientas y UI.

Eche un vistazo a los "anclajes de nodo" YAML y la "combinación de archivos" de YAML; podría ser la solución perfecta.

FYI: esta discusión continúa ahora en # 1380

@ Vad1mo Estoy de acuerdo en que extends queda corto en su caso. Hay muchas cosas que podemos hacer para mejorar esa experiencia. ¿Podrías abrir un problema por separado para que no nos desviemos aquí?

¡Por supuesto! Solo quería resaltar que esta podría ser una alternativa fácil y elegante.
Si compose extiende te lleva a la mitad del paso demasiado variable, entonces una mejora de compose-extiende hará que el paso de variables sea obsoleto. Tener menos conceptos para entender lo hace más fácil para el usuario.

Mi caso de uso es permitir $PWD en volumes , por lo que cada desarrollador del equipo puede clonar un repositorio en cualquier lugar y las rutas aún se montan correctamente.

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

@mattes Creo que ya es compatible, creo que .:/app es compatible

@aanand Como PoC hice un truco sucio de POSIX PE en Python . Para los sábados.

@kojiromike Se ve genial. Avísame si planeas continuar.

@aanand tengo la intención de hacerlo, pero definitivamente tiene algunos errores en este momento (y creo que puede haber sido una mala idea usar shlex ). Los informes de errores y las relaciones públicas son bienvenidos, por supuesto.

@dnephin ¿qué tal $HOME / ~ ?

@nafg Ambos son compatibles con la ruta de host de un volumen

@dnephin interesante, b / c de alguna manera terminé con un directorio llamado '$ HOME' ...

@aanand Como la propuesta "$ { VARIABLE: default }", con global_extends (o "import") esto se volvería bastante poderoso.

P: ¿Esto permitiría especificar el número de puerto que está expuesto al host? como - "$ {WEB_ PORT: 80 }: 80"?
El caso de uso es poder iniciar fácilmente varias instancias de una aplicación en la misma máquina / clúster, generalmente escuchando diferentes puertos o asignados a diferentes nombres de dominio locales.

Sí, podrías hacer eso.

Me gustaría usar vars en volúmenes junto con docker-compose scale my_app=3 . Tengo esto 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

Y quiero poder usar scale para agentes y usar volúmenes dinámicos para que mantengan los datos entre lanzamientos, por ejemplo:

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

Espero que también sea posible interpolar variables como parte del nombre de la imagen
Estamos usando https://github.com/openshift/source-to-image para construir un contenedor local en CI para cada rama y luego ejecutar pruebas en él usando docker-compose.
Ejecutar pruebas con imagen dinámica es bastante complicado con docker-compose y requiere renderizado manual de plantillas ..: -1:

Pero puede configurar COMPOSE_PROJECT_NAME para controlar el prefijo por ejecución para poder hacerlo ya, ¿verdad? Si es así, no es necesario tener una lógica compleja y archivos yml ilegibles alrededor de los nombres.

@andrerom no me sigue. Según los documentos que controlan el siguiente Sets the project name, which is prepended to the name of every container started by Compose mientras intentamos establecer una propiedad de imagen en su lugar:

web:
  image: <I_AM_DYNAMIC>

ah, mi error.

Pensé que querías decir

<I_AM_DYNAMIC>:
  image: nginx

La referencia dinámica de la imagen (y construcción) tendría mucho sentido. Por ejemplo, cambiar entre contenedores base de depuración y no depuración para su lenguaje de programación, por ejemplo, sería un buen caso de uso para esto.

Caso de uso adicional _ (que podría ser lo que @ Maxim-Filimonov tiene en mente) _: poder anular qué etiqueta usar de una imagen, para que pueda usar: último por defecto, pero cambie para probar fácilmente otra cosa sin cambiar yml file _ (necesario para los casos de uso de CI básicamente) _.

@andrerom ese es exactamente nuestro caso de uso: +1:

¿Esto también funcionará para cosas como?

web:
  environment:
    - FOO=${whoami}

@ k0377 No creo que lo hagan, porque eso es realmente algo que maneja el shell, pero puedes agregar el resultado en una variable de entorno y usar eso.

En este caso particular, la variable de entorno $USER probablemente le dará lo mismo.

@aanand ¿

Como se mencionó anteriormente, implementar nuestras propias plantillas no es una tarea trivial (y las expresiones regulares no son tan interesantes), por lo que deberíamos usar una ya existente, que demostró ser sólida.

Alternativamente, podríamos usar ancors y referencias YAML https://gist.github.com/bowsersenior/979804

Pero luego estamos limitados en el uso de variables (inyecte el nombre de la variable en medio del contenido).

+1 para Jinja2: ciertamente encajaría en el molde y ansible lo usa para
exactamente ese caso de uso (plantillas en archivos yml)

El martes 26 de mayo de 2015 a la 1:25 p.m., tonnzor [email protected] escribió:

@aanand https://github.com/aanand ¿Por qué no utilizar ninguna plantilla existente?
motores que ya están presentes? Jinja2 está ahí y funciona bien.

Como se mencionó anteriormente, implementar nuestras propias plantillas no es una tarea trivial
(y las expresiones regulares no son tan interesantes) por lo que deberíamos usar una ya existente,
que demostró ser sólido.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105493447.

Jinja2 hace un _mucho_ más de lo que necesitamos:

  • condicionales
  • bucle
  • extensión / herencia
  • comentarios
  • filtros

No vamos a agregar nada de eso a Redactar. Si Jinja2 se puede configurar para solo interpolar variables, entonces podría ser un candidato.

En realidad, hacer un bucle puede ser interesante.

Suponga que tiene una lista de clientes para los que desea iniciar contenedores
donde pones algunas variables específicas del cliente en el entorno.

La extensión / herencia puede ser interesante para mejorar la
mecanismo de extensión rudimentario.

Los filtros pueden ser excelentes para hacer algo con las variables existentes.

El martes 26 de mayo de 2015 a la 1:56 p.m., Aanand Prasad [email protected]
escribió:

Jinja2 hace un _mucho_ más de lo que necesitamos:

  • condicionales
  • bucle
  • extensión / herencia
  • comentarios
  • filtros

No vamos a agregar nada de eso a Redactar. Si se puede configurar Jinja2
para simplemente interpolar variables, entonces podría ser un candidato.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105498909.

Pueden ser características interesantes, pero vienen con mucha más complejidad de la que me siento cómodo presentándoles tanto en Compose como en el formato de archivo, y estaríamos vinculando ambos a un lenguaje de plantillas específico con (hasta donde yo sé) una sola implementación. y sin especificación. Simplemente no es factible.

@aanand Algunas notas aquí:

  1. Jinja2 es sólido y lleva unos minutos hacer el preprocesamiento de YAML con él:

de la plantilla de importación jinja2
template = Template ('¡Hola, {{name}}!')
template.render (nombre = "Aanand")
¡Hola Aanand!

Si desea más seguridad, puede usar una caja de arena inmutable:

de jinja2.sandbox importar ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('¡Hola {{nombre}}!')
template.render (nombre = "Aanand")
¡Hola Aanand!

En nuestro caso sería:

importar sistema operativo
de jinja2.sandbox importar ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('¡Hola, {{nombre}}!')
template.render (** os.environ)

  1. ¿No queremos filtros? Con el filtro, puede definir el valor predeterminado fácilmente ({{valor | predeterminado ("predeterminado")}})
  2. ¿Realmente debemos preocuparnos por los usuarios que usan funciones extendidas de Jinja para atornillar el archivo YAML? De la misma manera, el usuario podría generar un archivo YAML no válido manualmente. Creo que deberíamos mantenerlo simple: intente procesar la plantilla Jinja dada y devuelva el error si hubo un error o el YAML producido no es válido (lo mismo que hace ahora).
  3. Si no ve Jinja2 como solución, sería genial al menos usar {{variable}} como sintaxis.
  4. Django usa regexp para analizar y generar plantillas. Es apto para producción durante mucho tiempo y se adapta bien a él.

importar sistema operativo
importar re
template = "¡Hola, {{name}}!"
re.sub ("{{\ s _ ([a-zA-Z0-9 _] +?) \ s_}}", lambda m: os.environ.get (m.group (1), ''), plantilla)

En cualquier caso, necesitamos que esta función funcione, sea cual sea la solución que tomemos.

Estoy +1 en el uso de una solución de plantillas genéricas si se consideran las plantillas. Por ejemplo, http://mustache.github.io , que está disponible en muchos idiomas. Este es solo un ejemplo, otros motores de plantillas se pueden considerar igualmente

@aanand entiendo totalmente tu punto. También me gusta la sencillez y
sucinto del compose dsl.

Quizás esto debería hacerse como un proyecto externo, dice el meta-compositor. Eso
toma un compose.tpl.yml y un variables.yml, crea un docker-compose.yml
y nos vamos.
Como mostró @tonnzor, se podría hacer con una pequeña pieza de código Python.

Esto ofrecería poderosas plantillas a aquellos que lo necesitan sin
introduciendo complejidad para tareas simples.

El martes 26 de mayo de 2015 a las 4:52 p.m., Sebastiaan van Stijn <
[email protected]> escribió:

Estoy +1 en el uso de una solución de plantillas _generic_ si las plantillas son
considerado. Por ejemplo, http://mustache.github.io , que está disponible en muchos
Idiomas Este es solo un ejemplo, otros motores de plantillas pueden ser
considerado igualmente

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Hmm ... También lo es la propuesta ahora de usar un lenguaje de plantillas dentro de compose.yml (que es un lenguaje descriptivo para componer contenedores de Docker), para cosas como command y entrypoint , que ya aceptan tanto exec y sh -c valores de estilo? Esto podría ser confuso, ya que después de la renderización de la plantilla, el comando de shell resultante presumiblemente todavía se interpretaría, por lo que si una variable se expandiera a * , se expandiría aún más. Escapar de secuencias en un idioma u otro se vuelve complicado cuando tienes tantas capas de interpretación fallida.

@kojiromike No estoy seguro de que se desee un motor de plantillas, ¡pero si se va a usar! mejor use algo bien conocido. La pregunta básica es; debería docker-compose escribir la sustitución desde cero, o usar algo existente.

El martes, 26 de mayo de 2015 a las 11:02 a. M. Christoph Witzany [email protected]
escribió:

@aanand entiendo totalmente tu punto. También me gusta la sencillez y
sucinto del compose dsl.

Quizás esto debería hacerse como un proyecto externo, dice el meta-compositor. Eso
toma un compose.tpl.yml y un variables.yml, crea un docker-compose.yml
y nos vamos.

Puede hacerlo hoy sin ningún proyecto nuevo. Estoy seguro de que jinja puede ser
invocado desde la línea de comando de alguna manera. Personalmente solo uso el envsubst
mando.

Lo que sería realmente útil es que compose pudiera leer el archivo desde stdin.
Eso eliminaría la necesidad de un archivo intermedio.

Como mostró @tonnzor, se podría hacer con una pequeña pieza de código Python.

Esto ofrecería poderosas plantillas a aquellos que lo necesitan sin
introduciendo complejidad para tareas simples.

El martes 26 de mayo de 2015 a las 4:52 p.m., Sebastiaan van Stijn <
[email protected]> escribió:

Estoy +1 en el uso de una solución de plantillas _generic_ si las plantillas son
considerado. Por ejemplo, http://mustache.github.io , que está disponible en muchos
Idiomas Este es solo un ejemplo, otros motores de plantillas pueden ser
considerado igualmente

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Responda a este correo electrónico directamente o véalo en 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 para leer el archivo de stdin. No tengo ningún problema con el uso de una solución de plantilla externa, pero sería bueno no tener archivos intermedios.

Suena como un gran primer paso y una característica común de muchas herramientas cli. Vamos a hacer eso

: +1:

Así por ejemplo

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

wfm. : +1:

Acabo de notar que la ventana acoplable / distribución maneja los valores primarios en el archivo yml a través de variables de entorno, pero usando un enfoque diferente https://github.com/docker/distribution/blob/master/docs/configuration.md#override -configuration-options

^^ @aanand

@thaJeztah, eso también funcionaría para nosotros. Podemos usar variables de entorno para anular comandos luego

DOCKER_COMPOSE_IMAGE_NAME='my_image:is_dynamic'

Enfoque interesante, pero no soy un fanático: nombres de variables de entorno detallados, mucha duplicación si desea usar un valor en varios lugares, todo está implícito, sin interpolación dentro de cadenas.

@aanand tampoco se

Me encontré con https://github.com/kelseyhightower/confd que podría ser de interés. Utiliza http://golang.org/pkg/text/template/#pkg -overview

@olalonde desafortunadamente, docker-compose está escrito en Python, por lo que Go-templates no funcionará.

@aanand soy +20 en tu propuesta original, con la modificación de que incluso las imágenes y especialmente las etiquetas deberían ser posibles de inyectar. Solo hazlo, nos ahorraría a todos muchos envoltorios y manejo de configuración innecesario;)

Escribí un pequeño paquete de Python que me ayuda con eso. El plan es canalizar todos los comandos hasta la ventana acoplable para que pueda usarlo de manera equivalente.
Compruébalo en https://github.com/webcrofting/meta-compose/

meta-componer se ve muy bien. ¡Debería estar integrado para docker-compose!

Gran +1 aquí: no estoy entusiasmado con el preprocesamiento de plantillas, pero extraer las variables de entorno de una forma u otra sería genial. La expansión POSIX es probablemente más limpia que Jinja2, pero de cualquier manera está bien.

Gran +1 desde aquí también. Mi caso de uso es más para agregar soporte de ID de publicidad dinámica para el contenedor kafka, que es vital para los productores de datos (que podrían ser otros contenedores).

También estoy entusiasmado con esta función.

La expansión POSIX es probablemente más limpia que Jinja2, pero de cualquier manera está bien.

Creo que otro argumento a favor de la expansión POSIX es que no tiene lógica. Jinja2 admite cierto grado de lógica condicional / de bucle (como hacen la mayoría de los motores de plantillas, incluso los que dicen ser "sin lógica"). En mi experiencia, mezclar lógica de plantillas y YAML es bastante extraño. ¿Alguien puede pensar en un caso de uso para tal lógica? De lo contrario, sería mejor evitar específicamente el soporte por ahora.

Sería bueno tener una respuesta clara de los desarrolladores sobre esta función. Al leer varios temas y relaciones públicas, no está claro si realmente desea implementarlo o no.

Si es así, ¿con qué tipo de mecanismo? Si no lo hace, la gente podría comenzar a crear algunas herramientas de terceros para administrar la función.

Gracias !

Ok, acabo de ver https://github.com/docker/compose/pull/76. Supongo que la respuesta está ahí ...

Caminé algunos ciclos sobre los problemas vinculados / RP.

AFAIK, la comunidad nginx se negó a adoptar ningún motor de plantilla para archivos de configuración, incluso para una simple sustitución de variables. ¿Por qué? Quizás, todavía están eligiendo un motor de plantilla ideal: smile :

@hadim

Al leer varios temas y relaciones públicas, no está claro si realmente desea implementarlo o no.

Se suponía que este problema proporcionaría la respuesta definitiva a esa pregunta, así que lamento no haber sido claro: sí, queremos implementarlo, y con una sintaxis al estilo POSIX.

gracias @aanand !

Gracias, @aanand.

+1 para mí. Necesito pasar --dns = (dirección del puente docker0), y necesito que funcione si eso cambia en futuras versiones de docker, por lo que una variable de entorno y / o shell es perfecta. meta-compose no funciona para mí, ya que debería admitir DOCKER_HOST remoto y, por ejemplo, a través de docker-swarm, no solo localmente.

: +1: Esto sería muy bueno. Actualmente, termino generando el archivo .yml a través de otra secuencia de comandos, o simplemente no uso docker-compose por completo, y manualmente --link-ing dockers.

:Pulgares hacia arriba:

Creo que la interpolación básica de variables de entorno sería muy útil para cosas simples.

Un par de casos de uso simples:

  • Ser capaz de especificar dinámicamente la etiqueta de una imagen para extraerla de un repositorio remoto.
  • Poder configurar el mapeo de puertos para un contenedor.

Herramientas como Ansible ya funcionan muy bien con las plantillas, por lo que no estoy seguro de que se necesite un motor de plantillas completo. Pero no poder tener ningún contenido dinámico en el archivo comose.yml es muy limitante.

Con respecto al PR # 1488 combinado, estoy particularmente interesado en canalizar un archivo de configuración a docker-compose . No puedo entender por qué docker-compose no puede recoger de un proceso de nodo.

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

¿Algún ejemplo sobre cómo canalizar datos desde Node.js?

Otra cosa que he encontrado es que docker-compose 1.4.0-RC1 está enviando algunos mensajes aparentemente normales como Starting... o Attaching... al stderr lugar de stdout .

@kadishmal ¿Podría abrir números separados para estos, por favor?

Otra sintaxis / implementación candidata: la plantilla de cadenas de Python, como se especifica en PEP 0292 e implementada en string.Template .

Es muy similar a la expansión de parámetros POSIX:

  • $foo expande al valor de foo
  • ${foo} expande al valor de foo
  • $ , ${ , $} , ${} , ${foo , $ {foo} , ${ foo} , ${foo } son errores

Inconvenientes:

  • Sin valor predeterminado o sintaxis de "valor requerido". Aún así, podríamos decidir más tarde si queremos que sean suficientes para merecer escribir nuestro propio código de plantillas.
  • Los mensajes de error no exponen ninguna información legible por máquina sobre dónde está el error de sintaxis (es decir, sin realizar una coincidencia de expresiones regulares en la cadena de error).
  • La sintaxis de escape difiere de POSIX: $$ lugar de \$ .

En realidad, esto podría ser una bendición disfrazada: a YAML no le gusta \$ y requiere que escapes dos veces. No creo que sea bueno decirle a la gente que escriba \\$ solo para obtener un signo de dólar.

He mejorado una implementación en # 1765.

+1

No estoy seguro de si este es el lugar adecuado para esto o si debería hacer un nuevo número.

Creo que la prioridad de env debería ser al revés, es decir, una variable del shell que invoca docker-compose debería anular cualquier variable dentro de docker-compose.yml, que a su vez debería anular cualquier variable definida por el contenedor.

Esto es lo que sucede actualmente cuando lo intento:

docker-compose.yml:

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

y luego ejecútelo con el comando env :

docker-compose run test env | grep FOO

da FOO="from compose" , como se esperaba. Pero entonces:

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

también da FOO="from compose" , pero aquí estaba esperando FOO="from shell" .

Es posible que algunas personas también necesiten interpolación de variables para otros casos de uso, pero cambiar esto satisfaría el caso "predeterminado": de hecho, la definición / valor environment: en docker-compose.yml es el predeterminado y se puede anular en tiempo de ejecución si es necesario, sin necesidad de sintaxis YAML adicional.

@fazy , no tuvo en cuenta que el comando env se ejecutó en el contenedor test aislado en el que el FOO es from compose (solo como debería ser y como estaba configurado en un archivo docker-compose ). Pero fuera de ese contenedor, si el proceso docker-compose tuviera algún tipo de función de impresión para la variable de entorno que configuró antes del comando, se habría impreso 'desde el shell' porque es el valor para el host (así como para el proceso docker-compose ) en el que lo está ejecutando. Tal vez esperabas que el FOO fuera from shell en este caso, pero personalmente me sorprendería mucho si lo fuera. (Espero que a pesar de mi inglés entiendas mi punto).

@smileart gracias, creo que veo lo que estás diciendo.

Sin embargo, el contenedor test no está completamente aislado, obtiene su entorno de docker-compose (o al menos, docker-compose puede establecer variables de entorno en el contenedor iniciado) y docker-compose él mismo puede ver la variable de entorno "exterior".

Puedes ver con este docker-compose.yml:

test:
    image: ubuntu
    environment:
        - FOO

Entonces el comando:

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

de hecho da el resultado "desde shell".

Entonces mi pregunta es sobre la precedencia. Solo especificando el nombre de la variable aquí, - FOO , puedo inyectar la variable desde fuera. Pero si especifico - FOO=something _y_ inyecto una variable desde el exterior, ¿cuál debería tener prioridad? En mi humilde opinión, la variable especificada en la línea de comando debe tener prioridad sobre el archivo de configuración.

@fazy Oh, lo siento, no he probado FOO="from shell" docker-compose run test env | grep FOO sin especificar su valor en docker-compose.yml y no sabía que nos da el FOO del host. Entonces, no solo ya es extraño para mí: smiley: pensé que configurar una variable de entorno antes de que docker-compose influyera en docker-compose y docker-compose SOLAMENTE sin tirarlo al envase. Ahora veo lo que quisiste decir.

Me encontré con el inconveniente de escapar de $ mencionado en https://github.com/docker/compose/issues/1377#issuecomment -124571722. Primero hice FOO=ba$e luego FOO='ba$e' (olvidando que se tomó "desnudo"), luego FOO=ba\$e , luego FOO=ba\\$e , luego me di por vencido y fui a los documentos, solo para sorprenderse al encontrar que " $ es el carácter de escape para $ ". Para mí, esto no fue particularmente "menos sorprendente".

Sin embargo, no sé cuál sería la buena solución.

@ ct-clearhaus Compose no es el único programa que usa $ para escapar de $ . También encontrará esto en archivos MAKE. Entonces, para algunas personas este idioma es bastante familiar.

Me encanta la implementación de sustitución de variables existente. Sin embargo, realmente podría usar la capacidad de establecer un valor predeterminado, según la propuesta original de @aanand . Creo que la sintaxis POSIX es perfecta:

${ENV-default}

Mi uso específico es que quiero poder especificar el puerto de host en el que se ejecuta el servicio:

PORT=8123 docker-compose up

Al agregar esto a mi docker-compose.yml :

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

¿Sigue esta función en el plan y en proceso?

Intenté resolver mi problema con extensiones , pero se volvió bastante complicado. No solo tuve que duplicar casi todos mis docker-compose.yml solo para cambiar una configuración, tampoco hay forma de _cambiar_ una configuración de puerto expuesta, solo puedes add to la lista de puertos expuestos, que no es ideal para mí.

¿Por qué docker-compose no falla cuando las variables de entorno no están configuradas? Simplemente registra una advertencia y continúa. No solo regresar y el error sería un mejor enfoque ...
WARNING: The FOO variable is not set. Defaulting to a blank string.

+1 para la sintaxis POSIX para declarar valores predeterminados

Tal vez me esté perdiendo algo obvio, pero me gustaría poder usar variables de entorno de un archivo env_file para establecer el valor de una variable de entorno, por ejemplo:

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}

¿Podría lograrse de alguna otra manera? No quiero tener un archivo de plantilla yaml que deba canalizarse a través de envsubst.

¿Por qué no poner este valor directamente en el env_file la forma que desee?

2636 admitirá un archivo env para valores predeterminados

Eso significaría tener una variable que debe tener el mismo valor en dos lugares, lo hace más fácil si solo necesita cambiar uno. # 2636 parece prometedor.

Necesitamos desesperadamente un mecanismo para admitir variables predeterminadas ahora, ya que las limitaciones existentes nos obligan a usar scripts de envoltura para ayudar a docker-compose. Necesito cosas como NODE_ENV=${NODE_ENV:-dev} para trabajar, y por conveniencia sería bueno tener SOME_NUMBER=$((96*60)) para trabajar. ¿Estaba esto programado para una próxima versión?

+1 para valores predeterminados

+1 para valores predeterminados. esto se está volviendo crítico para nosotros.

Estoy de acuerdo @ darkn3rd - Necesito obtener la identificación del usuario y la identificación del grupo de usuarios para configurarlos en el contenedor. La única forma que encontré es forzar a mi equipo a exportar 2 vars ... o usar un archivo MAKE que hice para exportarlos.

Si tan solo pudiera hacer:

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

eso resolverá todos mis problemas

@mgor Parece que podrías pasarlo por envsubst ?

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

debería hacerlo (sin contaminar el medio ambiente persistente), creo.

@OJFord @mgor No envset y slv .

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

envset cargará variables de un archivo env en la sesión de shell actual, slv reemplaza la plantilla usando variables ambientales.

Estoy de acuerdo @OJFord pero eso no es lo que necesito ...
Permítanme precisar: somos un equipo de 40 desarrolladores que utiliza diferentes pilas de docker-compose. Estamos usando git para obtener código.

Si les pido que modifiquen docker-compose.yml que es entregado por nuestro git, entonces estoy seguro de que alguien enviará un archivo docker-compose.yml modificado ... Créame, ese será el caso.

Puedo "generar un archivo compositor base" que es ignorado por git y extendido por docker-compose.yml, pero para generarlo tendré que darles un Makefile o un bashscript ... Llegará el día en que un "base docker file "será necesario cambiar, y el equipo no se dará cuenta de que tendrá que volver a ejecutar la generación.

Lo mismo para un archivo "env", eso es muy bueno, pero no funciona con "build" y necesito pedirle a mi equipo que genere este archivo.

Realmente, si docker-compose puede obtener valores de bash (o cualquier otra solución que devuelva algo más que una var ENV) en el archivo yaml resolverá muchas necesidades.

Mi ejemplo en mi comando anterior es perfecto: necesito obtener la identificación de usuario y gid y esos valores no están establecidos por ENV vars. Así que necesito pedirle a mi equipo que escriba sus ID en un archivo .env ... Simple para mí y para ti, no para todos.

Para precisar: necesito proporcionar un archivo docker-compose que el equipo no debería cambiar, porque está en un repositorio de git.

Esta solicitud de extracción es un ejemplo simple que me funciona. Quizás puedas ayudarme a hacerlo mejor.

Intenté con el entorno y las directivas de usuario del archivo docker-compose.yml. Funciona bien por ahora.

El valor predeterminado debería estar allí ... Muy útil ... Los desarrolladores y OPS están usando los registros de la ventana acoplable o el syslog ... Por lo tanto, generalmente tienen que crear el LOG_FORMAT predeterminado que se muestra a continuación ... Podríamos tener el valor predeterminado y solo úselo cuando cambie a 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"

¿Cuándo estará disponible? Estoy en Compose 1.7.0 y esto todavía no está ahí :(

Por favor, indíquenos los valores predeterminados.

@marcellodesales : Quizás pueda aprovechar el uso de un archivo docker-compose.override.yml de alguna manera. Compruebe esa característica.

También +1 en env vars. Hoy en día, es nuestro principal problema con docker-compose.

Insistiría en mi PR # 3367 para poder obtener ciertos valores del host. :)

@pataquets No creo que quiera crear otro archivo de anulación ... nuestro archivo base.yml , como se muestra arriba, muestra todas las cosas compatibles en términos de controlador de registrador, etc ... Solo quiero cambiar y tener valores predeterminados. Creo que necesitaríamos mantener aún más archivos yml. Pero lo tendré en cuenta por si acaso.

+1

+1

+1

+1

¿Algún aviso sobre el uso de variables de entorno en docker-compose?

+1

+1

FYI: Las variables de entorno para docker-compose funcionan a partir de 1.7.0. También puede configurar las variables predeterminadas de la ventana acoplable-componer en .env en el mismo directorio que su archivo raíz docker-compose.yml . Esto no debe confundirse con los archivos env del motor Docker, ya que eso es algo diferente.

¿Hay alguna forma de establecer el nombre del servicio como variable?

En lugar de escribir esto

services:
   site_db:
     image: mysql:5.7

Podríamos escribir

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

Mi objetivo es mantener el mismo docker-compose.yml en varios sitios y solo cambiar el archivo .env . En este momento, todavía necesito modificar el nombre del contenedor porque estoy ejecutando varias aplicaciones en el mismo host. Y me gustaría que cada servicio tenga su propio nombre para mayor claridad.

@LouWii puedes usar

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

o (formato de archivo de redacción 2.1 y superior)

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

Pero, ¿por qué no establecer el nombre del proyecto? El nombre del proyecto es _intendido_ para eso, ya que antepone / antepone los nombres de los contenedores que se crean para evitar conflictos con otros proyectos en el mismo host. Ver https://docs.docker.com/compose/reference/envvars/#/composeprojectname

@thaJeztah ¡Gracias! Todavía estoy aprendiendo cómo funcionan Docker y Docker componen. Establecer el nombre del proyecto parece ser una mejor opción, tiene mucho sentido en mi uso.

¿Hay alguna forma de escribir dentro de las llaves interpoladas? Por ejemplo ${HOST_PORT + 1} .

Podrías canalizar el archivo a través de Jinja o algo ...

El martes 24 de enero de 2017 a las 5:36 a. M. Sam A. Horvath-Hunt [email protected]
escribió:

¿Hay alguna forma de escribir dentro de las llaves interpoladas? Por ejemplo, $ {HOST_PORT

  • 1}.

-
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/docker/compose/issues/1377#issuecomment-274767368 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAGAUN5ZrU39dnVVVASwIHr5mGqJFxh3ks5rVdRIgaJpZM4EMysO
.

¿Puedo escapar de $ ?

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

Actualmente, esto da como resultado la interpolación de la variable PATH del host y no el contenedor

¿Se encuentra un archivo docker-compose.yml solo uno?
¿Cómo puedo agregarlo o modificarlo?
Gracias por adelantado

@logicminds, aunque no pude encontrarlo documentado en ninguna parte, encontré que $$ interpola a un $ escapado.

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

@elquimista tiene una solución que he encontrado útil https://github.com/mhart/alpine-node/issues/48#issuecomment -430902787

¿Fue útil esta página
0 / 5 - 0 calificaciones