Moby: Agregue soporte para la función `extended` en Compose v3 / docker stack deploy

Creado en 16 feb. 2017  ·  165Comentarios  ·  Fuente: moby/moby

Como se puede ver en https://github.com/docker/compose/issues/4315 , la función extends que existe en docker-compose parece ser popular entre los usuarios a pesar de sus defectos. Sin embargo, hasta ahora no se ha agregado en la implementación del formato Compose del motor. Hasta ahora, hemos aconsejado a los usuarios que simplemente aplanen su estructura de archivos Compose cuando usen v3, pero ¿es esta la solución a largo plazo con la que queremos ir? ¿Cómo podemos proporcionar una ruta de actualización clara para los usuarios que han llegado a confiar en esta función?

cc @dnephin @vdemeester

arestack kinfeature

Comentario más útil

No solo esto, sino que el registro de cambios dice "esto se ha eliminado, consulte 'cómo actualizar' para obtener más detalles". Miro "cómo actualizar" para, ya sabes, detalles sobre cómo actualizar, y lo que dice es "ver 'ampliar servicios' para obtener más detalles". Voy a "extender servicios" pensando que finalmente veré una manera de extender mis archivos, solo para ver "esto se ha eliminado, consulte el registro de cambios para obtener más detalles".

En este punto, esto parece una broma cruel que está jugando el escritor de documentación.

Todos 165 comentarios

Agregué algunas notas https://github.com/docker/compose/issues/4315#issuecomment -280617251 para traerme las extensiones que existen hasta la versión 2.1 del archivo de composición de docker no es una buena idea, pero la característica principal es miss es poder declarar servicios abstractos (que nunca deben ejecutarse, pero que podrían usarse para agrupar propiedades comunes de servicios por conveniencia).

Estuve de acuerdo con los comentarios de docker / compose # 4315 de que la forma en que extends funcionaba era un poco espartana.

No recomendaré una solución, pero FWIW, para mostrar el alcance del abuso, aquí están las convenciones que adornan la parte superior de nuestro archivo de redacción:

#
# Docker Compose configuration
#
# Due to lack of "expressivity" in Compose, we define our own couple of service
# "pseudo-types":
#
#   - image-only services (name: *-image)
#
#     The only goal of these is to build images. No other services build images.
#
#     These have entrypoint overridden to exit immediately.
#
#   - base services (name: *-base)
#
#     These contain common configuration and are intended to be extended.
#
#     Their command (not entrypoint, to keep the original one) is overridden to
#     exit immediately. Service must support a command to exit immediately.
#
#   - task services (name: *-task)
#
#     These are intended for running one-off commands.
#
#     Their default command is overridden to exit immediately. Service must
#     support a command to exit immediately.
#
#   - "real" services
#
#     These are actual services that stay up and running.
#
version: '2'
services:
  ...

Creo que la extensión de la versión 2.1 es una buena opción. Extends es realmente simple y comprensible, esta es una buena práctica para que cada entorno tenga una pequeña y legible transformación entre dev, prod y env.

De hecho, tengo

  • un archivo común de docker-compose que presenta las reglas base
  • un dev docker componga extendiéndolo y con facilidades para el desarrollador
  • una ventana acoplable de staging componga ampliando también común y con facilidades para este ambiente
  • una ventana acoplable de producción que se compone también en común y con facilidades para este entorno, especialmente replicación de contenedores, reglas de reinicio, etc.

Esto funciona, y no entiendo por qué deberíamos buscar en este ticket una reescritura completa, sino más bien mantener una característica interesante. La extensión es una buena parte con casos de uso especiales que otras técnicas no pueden resolver fácilmente. Estoy contento con la ampliación de posibilidades.

También nos impide actualizar al formato v3.x.

Mantenemos nuestras definiciones de contenedor de la ventana acoplable en un diseño de carpeta por instancia, donde cada carpeta contiene un docker-compose.yml que define las especificaciones de env para la instancia del contenedor en cuestión. Para factorizar las cosas comunes (DRY) usamos definiciones de servicio base en una carpeta principal y usamos extend .

Entonces, cuando necesito administrar una instancia de contenedor en particular, solo necesito cd en la carpeta correcta y luego puedo ejecutar directamente los comandos de docker-compose sin más configuración (no se requieren banderas de -f que los miembros del equipo necesita buscar o saber, simplemente funciona como se esperaba de inmediato).

No puedo usar archivos de redacción de la versión 3.

Utilizo services.yml para definir el diseño base de mis servicios y luego lo extiendo con dev.services.yml para mi entorno de desarrollo (principalmente agregando volúmenes) pero me gusta la reutilización (DRY) de las extensiones cuando estaba adicional. No es un factor decisivo, pero me impediría pasar a la versión 3 a menos que haya una función imprescindible.

Sin embargo, no estoy en contra de mejorar la solución de 'extensión' v2.1 con algo más apropiado. Algo como los servicios abstractos podría ser más seguro de usar y más poderoso.

Por ejemplo (dado que es abstracto) podría imaginarme el soporte de volúmenes / puntos de montaje / redes abstractos, donde el servicio base abstracto define un punto de montaje local o una red requerida para un servicio, sin definir la parte del host, lo que significa que un servicio derivado podría definir / mapear la parte del anfitrión de los montajes / volúmenes y redes a lo que sea apropiado en su entorno anfitrión / escenario.

Ese es un ejemplo de algo que no podemos hacer ahora con 'extiende' hasta donde yo sé, y abriría algunas posibilidades interesantes.

Quitar la función de extensión no fue útil en absoluto. Tenemos muchos servicios web iniciados con los mismos volúmenes mapeados, variables de entorno y etiquetas establecidas. También tienen las mismas políticas de chequeo de salud. Y sin mencionar los puertos. Combinar archivos de redacción con la opción -f múltiple es tedioso y propenso a errores si se trata de varios proyectos en el mismo host.

@ shin- ¿se volverá a incluir en el esquema 3.2?

Realmente, realmente me encantaría volver a poner extends en el formato de archivo. Lo he estado usando para refinar aún más los servicios abstractos para varios proyectos. Entiendo que múltiples opciones de -f ajustan casi a la factura, pero no siempre funcionan. Por ejemplo, con bastante frecuencia cambio el nombre del servicio abstracto por algo más significativo en el contexto del proyecto en cuestión. Esto es algo que no admite la anulación que se produce con varias opciones -f .

Sin embargo, no me importaría perder el extends exacto, siempre que haya alguna otra forma de "instanciar" un servicio abstracto en un archivo.

Tengo una configuración con un archivo de servicio común y un montón de servicios que lo extienden, cambiando principalmente los volúmenes, por lo que diría que confío en la función extends y no veo otra buena manera de describir mi configuración.

--frustrated

+1
Puedo ver la lógica detrás de la recomendación de aplanar los archivos de composición acoplable, pero no me gusta la idea de duplicar el código que define la topología de nuestro servicio de desarrollo en varios proyectos. Usaremos la solución -f por ahora, con scripts de shell para que los desarrolladores no tengan que recordar qué servicios incluir en qué casos.

¡Espero que se pueda encontrar una solución satisfactoria aquí para permitir una mejor factorización de las estructuras de composición!

En la parte superior de mi lista de casos de uso está DRYup mi conjunto de servicios administrados por configuración. Pensé que podría aprovechar las 'extensiones' si v3. No quiero volver a v2 ... y no quiero tener casos especiales en los que deba utilizar el proceso -f como solución alternativa.

Oye, ¿alguien empezó a trabajar en esto? No puedo encontrar un PR para realizar un seguimiento. También nos simplificaría mucho algunas cosas aquí (caso de uso muy similar a algunos descritos anteriormente).

Dado que la versión 3 está congelada y necesitaba una forma de compartir la configuración común, pirateé una pequeña solución alternativa, que creo que podría compartir aquí (no estoy seguro de si este es el lugar correcto, pero siéntase libre de decirme dónde más puedo comparte esta información :))

No voy a dar más detalles aquí, ya que hay un archivo Léame en el repositorio.
Que tengas una buena, todos ☮️

Editar:

Lo siento, aquí está el enlace: D

+1

+1

+1

Gracias por los +1 💃
Mientras tanto, encontré otra imagen de docker noop , que es más pequeña en un factor de 10 ^ 3 (debido a que el noop real está escrito en ensamblaje).

Desafortunadamente, no hay ninguna licencia en ese repositorio. Ya le escribí un mensaje al propietario en facebk pero aún no respondió. Tal vez agregue una licencia si más personas le preguntan al respecto :)

Algo que podría ayudar a algunos de los casos de uso extendidos (aquellos dentro de un solo archivo) sería el soporte para anclajes YAML: https://learnxinyminutes.com/docs/yaml/

Parece que el esquema JSON puede estar fallando la validación en ellos service must be a mapping, not a NoneType. .

Oye, @grayside , las anclas de yaml funcionan, al menos para mí. Vea mi comentario arriba para saber cómo los uso.

Ok, pero es muy triste usar algún servicio noop, ¿no?

Especialmente para env vars, ¿qué tipo de valores manejan esos env vars? Si se trata de secretos, use la función de secretos de enjambre (o cualquier otra solución de secretos). Si se trata de configuraciones, estamos de acuerdo en que la mayoría de las configuraciones de tiempo son específicas de la aplicación / servicio, no están diseñadas para ser compartidas entre servicios.

Si necesita compartir configuraciones entre servicios, la mayoría de las veces es cuando lanza la misma imagen de contenedor pero para diferentes propósitos / tareas de tiempo de ejecución (consumidor, productor, trabajador http, ...).

Si se trata de configuraciones, estamos de acuerdo en que la mayoría de las configuraciones de tiempo son específicas de la aplicación / servicio, no están diseñadas para ser compartidas entre servicios.

Tiendo a no estar de acuerdo. En el proyecto en el que estoy trabajando actualmente, lo uso, por ejemplo, para volúmenes:

# Volume paths
environment:
  - &volume_a        volume-a:/usr/share/my_project/volumes/volume-a
  - &volume_b        volume-b:/usr/share/my_project/volumes/volume-b
  - &volume_c        volume-c:/usr/share/my_project/volumes/volume-c
  - &volume_d        volume-d:/usr/share/my_project/volumes/volume-d

Ahora puedo especificar estos volúmenes así:

volumes:
  - volume-a:
  - volume-b:
  - volume-c:
  - volume-d:

services:
  some-service:
    image: some-image
    volumes:
      - *volume_a
      - *volume_b

  some-other-service:
    image: some-other-image
    volumes:
      - *volume_b
      - *volume_c

  some-third-service:
    image: yet-another-image
    volumes:
      - *volume_a
      - *volume_b
      - *volume_c
      - *volume_d

Esto hace que sea mucho más fácil navegar por diferentes volúmenes sin tener que pensar en el contenedor en el que se encuentra. En mi humilde opinión, esta es una forma de hacer que su configuración de docker-compose sea más consistente y más fácil de usar y mantener.

Ok, sí, entiendo a @JanNash, pero en su ejemplo a continuación no tiene ningún servicio noop, ¿verdad?

Pero las anclas no son suficientes en muchos casos.

Mi caso implica el soporte de varios entornos para un mismo proyecto. Puedes ver un andamio para nuestros proyectos aquí .

Cuando desarrolla, usa devel.yaml , pero en producción usa prod.yaml . También hay test.yaml . Todos ellos heredan de common.yaml y obtienen algunas variables comunes de un archivo .env .

Cada uno tiene sus propias peculiaridades:

  • devel environment tiene como objetivo la velocidad de desarrollo, por lo que utiliza build args que producen compilaciones más rápidas, monta volúmenes con el código de la aplicación desde la computadora del desarrollador y agrega algunos servicios ficticios que aíslan la aplicación del mundo exterior.
  • prod busca la estabilidad en su lugar, por lo que descarga y compila todo el código, y lo agrupa en la imagen en lugar de usar volúmenes. Las compilaciones son más lentas, pero más seguras.
  • La prueba tiene como objetivo ser exactamente como prod, pero con aislamiento de los servicios externos, para evitar contaminar el mundo externo.

Esta simple separación permite tener una canalización de DevOps muy ágil y flexible, donde todos usan el mismo código entre diferentes etapas, con solo pequeños ajustes dependiendo del entorno en uso.

Traté de cambiar para componer el formato de archivo v3, pero no solo extends no es compatible, sino también .env , por lo que ahora mismo sería una pesadilla de mantenimiento (más por la falta de .env , para ser honesto). Al decidir entre Swarm y DRY, elegimos DRY por ahora, pero algún día necesitaremos Swarm y espero que ese día ambas funciones vuelvan a ser compatibles ... ☺️

... o al menos tenemos una forma de generar un formato sin DRY válido a partir de una solución DRY-ful. Pensé que docker-compose bundle era para eso, pero parece estar condenado a la desaprobación en este momento ...

... o tenemos una herramienta diferente que hace todo (también estoy vigilando ansible-container ). Pero seguramente esta no es "la solución".

El enlace en https://github.com/moby/moby/issues/31101#issuecomment -301212524 incluye un archivo README con el ejemplo de trabajo de los anclajes YAML. Revisándolo y probándolo de nuevo hoy, funciona bien. No estoy seguro de qué estoy haciendo de manera diferente.

@JanNash 👍

@Yajo, te escucho y, como dije, es una solución alternativa y sería mejor en un orden de magnitud si hubiera una buena solución DRY incorporada proporcionada por docker / moby / docker-compose (cualquiera que sea la referencia correcta) . Esperemos que eso suceda pronto porque, aparte de eso, estoy bastante contento con docker compose 👍

~ En aras de perder el soporte .env, también pirateé una solución alternativa (mi proyecto aún no está en producción, por lo que mi charla es un poco barata, lo sé :)). Para admitir diferentes conjuntos de variables de entorno (dependencia y versiones / etiquetas de imagen, por ejemplo) en diferentes entornos (para mí en este momento, eso es desarrollo local y un pequeño servidor de desarrollo), utilizo dos archivos, local.env y development.env y en lugar de ejecutar mis comandos con solo docker-compose <command> , o bien obtengo el archivo .env respectivo en mi shell antes, o lo ejecuto así: (. local.env && docker-compose <command>) . Sigue siendo un truco, pero por ahora, estoy bastante contento con esto. ~

Que tengas una buena, todos ustedes 🚶

Quizás incluso dos órdenes de magnitud: D

@JanNash espera! ¿ .env no se admite en 3 ?

En realidad no lo sé, acabo de leer en un comentario que no lo era.
He estado usando el procedimiento local.env y development.env principalmente porque no sabía sobre autoenv cuando lo implementé: D
Perdón por la posible confusión.

Ah, @Yajo mencionó que faltaba el soporte .env en este comentario .
¿Podrías explicarme, @Yajo?

Oh lo siento, es mi culpa. No es que no esté funcionando, es solo que debes especificarlo con env_file: .env , en lugar de ser autodetectado como antes. Volvamos al problema original.

¿La discusión va a dejar caer extends alguna parte? Me encantaría leerlo antes de dar nuestro caso de uso porque creo que está bien entendido que era una característica bastante utilizada.

Hola, tengo una pregunta: ¿cuándo? ¿Cuándo el soporte "extendido" volverá a estar en v3?

@JanNash puedes ser mucho más pequeño que eso. Acabo de presentar un problema en github contra su repositorio, obtuve noop hasta 1200 bytes desde 750k en mi máquina.

Veo que no puedo usar extender en este momento en enjambre.
¿Alguna idea de cómo lanzar el mismo servicio con los mismos puertos de publicación y con un contenedor en el servicio que tiene 1 variable de entorno adicional?

+1 para ampliar el apoyo en el despliegue de la pila de enjambres

Hola,
Estamos ejecutando una aplicación de microservicios que se distribuye en varios repositorios de git (cada uno tiene su archivo docker-compose).
La implementación está dirigida por un archivo docker-compose "raíz" que extiende cada servicio: para nosotros, esta característica extends es realmente necesaria para la implementación de la pila.
Entonces también +1 para extender el soporte en el despliegue de la pila de enjambre
Gracias.

Puede usar la herencia simple YAML (consulte &default , <<: *default ) como solución temporal:

version: '3'
services:
  worker: &default
    build: .
    command: bundle exec rake jobs:work
    env_file:
      - .env
    volumes:
      - .:/app
    depends_on:
      - db
      - redis
    links:
      - db:postgres
  web:
    <<: *default
    command: bundle exec puma -C config/puma.rb -p 3000
    ports:
      - "3000:3000"
  spring:
    <<: *default
    command: bundle exec spring server

Por supuesto, la función extends es mejor

¿Qué tal cuando extiendes un archivo diferente?

Yaml no tiene función de extensión de archivos :(

¿Hay alguna actualización sobre esta función de un colaborador de Docker? ¿Está previsto que se vuelva a introducir? Si no es así, ¿hay planes para algo similar? Si no, porque no..?

@quolpr , me temo que su código de "herencia simple YAML" no reemplaza extends en la mayoría de los casos, ya que el "prototipo" (es decir, &default ) siempre será interpretado por Docker Compose como un servicio llamado worker . Por lo tanto, qué servicio a) debe estar bien definido, b) podría no ser deseado.

De todos modos, definitivamente una característica interesante.

@laugimethods también puede usar referencias YAML:

version: '3'
services:
  spring:
    build: ./app
    command: /bin/sh -c "bundle exec spring server"
    volumes: &default_volumes
      - ./app:/app:delegated
      - bundle:/bundle:nocopy
  worker:
    build: ./app
    command: bundle exec sidekiq -v -C config/sidekiq.yml
    volumes: *default_volumes

(preste atención a &default_volumes y *default_volumes )

Pero realmente no puedo entender por qué se eliminó la función extends 🤔

Para su información, para reemplazar la función de "extensión" que falta, ahora estoy usando una composición / combinación de archivos .yaml :
https://github.com/Logimethods/smart-meter/blob/master/README.md#docker -compose

extiende funciona, es simple y maduro, creo que si alguien ve extendido como un anti-patrón entonces simplemente no lo use, pero por favor no lo corte

¿Puedo pedir una explicación clara del enfoque previsto sin usar extends ? Lo uso ampliamente, particularmente cuando he heredado de archivos contenidos en submódulos de Git, lo que permite una definición de un metaproyecto que maneja el cableado de red entre aplicaciones, etc. Aunque soy muy consciente de que puedo especificar varios archivos docker-compose.yml y tenerlos anulados, ¿significa esto que tendría que especificar las interconexiones en la línea de comandos, en lugar de poder verificarlas en el control de fuente usando extends ? ¿O me he perdido alguna característica nueva en alguna parte de la v3?

Estoy usando mucho extends en varios proyectos para heredar un conjunto común de atributos de servicio para diferentes entornos y diferentes hosts (lea: uso extends para heredar de un archivo diferente).

Después de leer en estupor la eliminación de la palabra clave extends y tratar de encontrar un reemplazo que no requiera encadenar los archivos de composición de -f docker, tengo mucha curiosidad por saber cuál es la razón para eliminar extends .

Entiendo el problema con links y volume-from pero simplemente abstenerse de usarlos en archivos base yml parece lo mejor que se puede hacer.

Sería improbable quitarle la rueda a un auto solo porque _podría_ acostumbrarse a voltear el auto ... ¿verdad?

PD: noop and anchors parece interesante pero agrega complejidad innecesaria a los proyectos más simples ...

Como ejemplo muy, muy simple:

common/common.yml

services:
  web:
    image: alpine:3.6
    build: .
    environment:
      DOMAIN:
      PREFIX:

dev/docker-compose.yml

services:
  web:
    extends: ../common/common.yml
    service: web
  ports:
    - "8080:8080"

prod/docker-compose.yml

services:
  web:
    extends: ../common/common.yml
    service: web
  image: the-prod-image:latest-release
  ports:
    - "80:80"
    - "80:443"
  environment:
    NEW_RELIC_KEY:

¿Cómo se mantienen los principios DRY sin extends ?

Actualmente no veo ninguna razón para actualizar desde la versión 2.1 debido a esto.

@teodorescuserban ,

conexión en cadena -f docker componer archivos

¿Qué problema tiene eso? Puede crear sus propios scripts con alias cortos para llamar a docker-compose.

Utilice la siguiente estructura:

common / common.yml

services:
  web:
    image: alpine:3.6
    build: .
    environment:
      DOMAIN:
      PREFIX:

dev / docker-compose.yml

services:
  web:
    ports:
      - "8080:8080"

prod / docker-compose.yml

services:
  web:
    image: the-prod-image:latest-release
    ports:
      - "80:80"
      - "80:443"
    environment:
      NEW_RELIC_KEY:

Comandos

docker-compose -f common/common.yml -f dev/docker-compose.yml -p myproject up --build
docker-compose -f common/common.yml -f prod/docker-compose.yml -p myproject up --build

No conocía esa característica. Aunque hace que su CLI sea un 💩, puede funcionar.

Creo que si ese va a ser el reemplazo oficial de extends , entonces debería haber una manera de hacerlo más fácil.

Por ejemplo:

docker-compose.yml

version: "3"  # or whatever
extend:
  - ./common/common.yml
  - ./dev/docker-compose.yml
services: # Not required now
  # etc.

De esta manera, puede apuntar a un solo archivo docker-compose.yml que hace todo lo que necesita.

Una alternativa útil sería admitir varios archivos de redacción en la var COMPOSE_FILE env.

@Yajo

Una alternativa útil sería admitir varios archivos de composición en la var. Env COMPOSE_FILE.

De https://docs.docker.com/compose/reference/envvars/#compose_file :

Esta variable admite varios archivos de composición separados por un separador de ruta (en Linux y macOS, el separador de ruta es : , en Windows es ; ). Por ejemplo: COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml . El separador de ruta también se puede personalizar usando COMPOSE_PATH_SEPARATOR .

@ dermeister0 También puede fusionar permanentemente esos archivos con herramientas como https://github.com/ImmobilienScout24/yamlreader :

> yamlreader common/common.yml prod/docker-compose.yml > docker-compose-prod.yml
> docker-compose -f docker-compose-prod.yml -p myproject up --build

> cat docker-compose-prod.yml
services:
    web:
        build: .
        environment:
            DOMAIN: null
            NEW_RELIC_KEY: null
            PREFIX: null
        image: the-prod-image:latest-release
        ports:
        - 80:80
        - 80:443

@ dermeister0 gracias por su sugerencia, desafortunadamente, es una manera torpe de salir de ella. El uso de extends elimina la necesidad de saber exactamente cómo debe conectarlos en cadena. Si bien puedo vivir con hacerlo por mí mismo, nunca podría aplicar esta solución a mis queridos desarrolladores.

Sin embargo, no sabía que la variable COMPOSE_FILE env puede contener varios valores. ¡Gracias @gsong ! Eso es increíble y puedo usarlo (lo defino en el archivo .env ). Aquí hay un solo problema: en los archivos base / comunes también puedo tener algunos servicios que no necesito.

Tomemos, por ejemplo, un archivo común plano que define una base de datos y contenedores web. En la puesta en escena, los desea todos agrupados, pero en prod, querrá hosts separados para db y para web.

Además, docker-compose.override.yml se carga de forma predeterminada.

https://docs.docker.com/compose/extends/#understanding -multiple-compose-files

Utilizo este enfoque con la versión 3.3:

  • poner opciones de configuración y servicios comunes en docker-compose.yml ;
  • use docker-compose.override.yml para configuraciones y servicios de desarrollo específicos (como xdebug, por ejemplo);
  • use docker-compose.staging.yml para opciones específicas de configuración de etapas.

Nota: no ejecuto Docker en producción.

Usando este enfoque, puedo construir fácilmente localmente usando docker-compose build y cuando implemento en la puesta en escena utilizo:

docker-compose -f docker-compose.staging.yml -f docker-compose.yml build

Estoy usando Apache y no tengo archivos de host virtual separados para el desarrollo y la puesta en escena. He gastado bastante para evitar tener archivos diferentes. Al final, he visto que el único enfoque válido es usar <IfDefine> y variables de entorno (que configuré en la sección de entorno de los archivos yml), para incluir la configuración ssl, por ejemplo. Y utilizo TLD y prefijo de dominio, por lo que puedo tener algo como www.example.local http: //www.example.local/ : 8080 y www.staging.example.com http://www.staging.example.com / . A nivel local, los sitios web se ejecutan en http y en la puesta en escena en https. Con este enfoque, no tengo que mantener diferentes versiones de los archivos. Creo que se podría hacer lo mismo en producción, pero como dije, prefiero evitar Docker en producción, atm.

Los caminos son todos parientes, por lo que los contenedores funcionarán en cualquier entorno.

Mis 2 centavos

-Filippo

En mi caso, anteriormente usé algo como esto:

  • common.yml
  • devel.yml -> extendiendo common.yml
  • prod.yml -> extendiendo common.yml
  • docker-compose.yml -> local, git-ignored, enlace simbólico al entorno deseado (devel o prod).

Gracias a https://github.com/moby/moby/issues/31101#issuecomment -329482917 y https://github.com/moby/moby/issues/31101#issuecomment -329512231, que no conocía, ahora puedo pasar a v3 usando un esquema diferente:

  • docker-compose.yml -> lo que antes era common.yml
  • devel.yml -> anulando docker-compose.yml
  • prod.yml -> anulando docker-compose.yml
  • docker-compose.override.yml -> local, git-ignored, enlace simbólico al entorno deseado (devel o prod).

También puedo hacer los trucos necesarios utilizando la variable env, por lo que en mi caso el problema está solucionado. ¡Gracias! 🎉 (Lo siento, debería haber leído los nuevos documentos correctamente antes de quejarme).

PD: Aún así, extends sería algo bueno para recuperar, pero al menos tenemos una alternativa lo suficientemente justa. 😊

@ shin- Primero me decepcionó mucho ver que faltaba la función extends en 3.0 , pero los anclajes YAML (ejemplo: https://github.com/JanNash/docker-noop) serían un reemplazo más que suficiente.

Lo único es que, como en el ejemplo anterior, debe colocar sus anclajes en alguna sección válida de su archivo docker-compose.yml .

¿Podríamos obtener una propiedad templates (de nivel superior) o claves ocultas como en GitLab para ser más flexibles en la forma de definir los anclajes?

@ schmunk42 echa un vistazo a https://github.com/docker/cli/pull/452

El problema de confiar en docker-compose.override.yml es que presupone que solo tiene un tipo de anulación que necesita incluir y una capa de anulaciones.

En mi caso, quiero tener ciertos comportamientos comunes a todo el desarrollo local, pero es posible que necesite que sean sutilmente diferentes si el desarrollador está ejecutando Windows, OSX o Linux. Para mantener esto manejable en un contexto de docker-compose v3, tengo usuarios de Linux que operan con el mismo comportamiento que el entorno de prueba, lo que funciona, pero significa que están ligeramente desfasados ​​con otros desarrolladores.

Evito usar -f para el desarrollo local porque he descubierto que es muy propenso a errores humanos, y confiar en él como un conmutador para demasiadas cosas causa problemas. Seleccionar un archivo parece razonable, seleccionar varios es algo que evito imponer cuidadosamente.

Para su información, creo que una vez que el truco con x- mencionado anteriormente, y también la conexión en cadena de archivos docker-compose usando la variable COMPOSE_FILE en el archivo de proyecto .env , agregando el docker- compose.override.yml debería resolver todos los casos de uso que he encontrado hasta ahora.

Los anclajes yml también son algo ingenioso que tengo la intención de usar en un futuro próximo.

No estoy muy contento con la belleza del truco x- , pero puedo vivir con eso.

¡Gracias a todos por su aporte!

Parece que la eliminación de extends está causando mucha acidez estomacal y bloqueando el cambio a v3 o recurriendo a hacks. Me gusta la capacidad de definir un servicio de "plantilla" (o abstracto) que puede incluir algunas cosas comunes (por ejemplo, actualizar políticas)

Estoy trabajando en una sencilla utilidad de filtro de golang que puede preprocesar un archivo de composición de Docker con extends y escupir un archivo v3 limpio con las extensiones resueltas:
resolver-componer docker stack deploy -c docker-compose.yaml
(o ventana acoplable-componer)

¿Funcionará esto para al menos algunos de sus casos de uso / por qué errores?

@pnickolov Eso sería maravilloso para mí.

He estado buscando ansible-container (uso ansible personalmente, pero aún no en el trabajo), que parece que haría todo lo que necesito, pero un script como el suyo sería más preferible (menos abandono)

Siempre que pueda procesar de forma recursiva las claves extends: , ¡sería feliz!

Ok, parece que encontramos alternativas a extends ... 👍

Lo preocupante es el hecho de que la gestión de proyectos de Moby's no parece considerar el mantenimiento de la compatibilidad como un elemento clave. La compatibilidad hacia adelante es esencial para una adopción más amplia, especialmente para grandes aplicaciones implementadas en producción. ¿Cómo podríamos impulsar Docker Swarm / Docker EE cuando no hay garantía de que las características principales como extends permanecerán? 👎
Una buena reputación es difícil de ganar y fácil de perder ...

Personalmente, preferiría confiar en las características nativas de YAML para realizar la tarea que se maneja con extends en la sintaxis v2 , en lugar de un script personalizado o una solución más grande como ansible. Tenía problemas similares antes y comencé a escribir mi propio convertidor antes de que hubiera una solución como usar múltiples archivos .yml, etc. (https://github.com/schmunk42/yii2-yaml-converter-command), pero no fue así. una solución viable.

Para mí, también está bien desaprobar funciones, si esto se hace junto con una política de control de versiones; no puedes llevar cosas viejas para siempre, incluso si esto significa algo de trabajo de nuestra parte.

@ schmunk42 Está bien

  • la característica eliminada ya no se usa realmente o es un verdadero bloqueador de evoluciones
  • se anuncia de antemano
  • se proporciona una ruta de migración de inmediato

Desafortunadamente, ninguno de esos requisitos (en mi libro) se aplica a la desaprobación de extends ...

@laugimethods ¿Cuál es la razón por la que necesita usar v3 ?

@ schmunk42 Debido a Swarm:

Versión 3.x, la versión más reciente y recomendada, diseñada para ser compatible con Compose y el modo de enjambre de Docker Engine. Esto se especifica con una versión: '3' o versión: '3.1', etc., entrada en la raíz del YAML.

El comando docker stack deploy admite cualquier archivo de composición de la versión "3.0" o superior

Por cierto, mi comentario no solo está relacionado con extends , sino con cualquier depreciación (dolorosa) que pueda ocurrir en el futuro ...

Sí, nos enfrentamos al mismo problema debido al modo enjambre.

En primer lugar, me pregunté por qué diablos la CLI de la ventana acoplable ahora puede usar la entrada --composer-file . Pero de nuestros aprendizajes con docker/swarm parece bastante complicado ejecutar pilas en un enjambre (autogestionado) y hay varias buenas razones por las que esto se ha trasladado al motor.

Solo para señalar algunos de mis hallazgos aquí ... la transición de v2 a v3.4 está lejos de ser fácil.

Algunos de mis problemas:

  • hay otras opciones no compatibles como volumes_from , bastante fáciles de eludir, ya que queríamos eliminar eso de todos modos
  • .env archivos docker-compose ) no tienen ningún efecto con la CLI de Docker
  • especificar varios archivos de redacción ( docker stack deploy -c docker-compose.yml -c docker-compose.override.yml doro ) parece no funcionar correctamente, no hay ningún error, pero me parece que tampoco se fusionaron correctamente, pero tampoco hay un comando como docker-compose config para verificarlo
  • no existe un binario "fácil de instalar" (pre-lanzamiento) para docker-compose que admita la sintaxis v3.4 ; como el borde de Docker
  • las redes externas deben crearse con --scope swarm

CC: @handcode

Usando las últimas compilaciones

  • Docker 17.09.0-ce
  • docker-compose 1.17.0dev

Ahora estoy usando esta canalización de configuración para reemplazar mi uso de _extend_ y _noop_
Mantiene las cosas un poco más SECAS
Espero que esto ayude a alguien

base.yml (definiciones compartidas, este es un documento yaml válido, por lo que se puede combinar usando _docker-compose config_)

version: '3.4'
networks:
  net_back:
    external: true

base inject.yml (definiciones de anclaje compartidos, por desgracia no puede ser añadido a base.yml como anclas no pueden ser referenciados a través de diferentes archivos YAML, en vez éstos se inyectan como texto en foo.yml, no una forma ideal para hacer esto)

x-logging: &logging
  driver: json-file
  options:
    max-size: "50m"
    max-file: "2"

foo.yml (definición de pila genérica, hace referencia a objetos de base.yml , anclajes de base-inject.yml y objetos anulados en foo-dev.yml )

version: '3.4'
[[base-inject]]
services:
  foo:
    image: ${DOCKER_REGISTRY}/foo:${IMAGE_VERSION}
    volumes:
      - type: volume
        source: "volfoo"
        target: "/foo"
    networks:
     - net_back
    logging:
      <<: *logging

foo-dev.yml (por definición de pila de entorno)

version: '3.4'
services:
  foo:
    ports:
      - "8080:80"
volumes:
  volfoo:
    name: '{{index .Service.Labels "com.docker.stack.namespace"}}_volfoo_{{.Task.Slot}}'
    driver: local

Luego, el comando de implementación:

docker stack rm stack_foo && echo "waiting..." && sleep 3 &&
  cat foo.yml | sed -e '/base-inject/ {' -e 'r base-inject.yml' -e 'd' -e '}' > ./foo-temp1.yml &&
  export $(sed '/^#/d' ./dev.env | xargs) &&
  docker-compose -f base.yml -f ./foo-temp1.yml -f foo-dev.yml config > ./foo-temp2.yml
  docker stack deploy --with-registry-auth --prune --compose-file ./foo-temp2.yml stack_foo
  1. Quitar pila vieja
  2. Espere a que la pila extraíble se propague
  3. Inyectar anclas en una definición genérica, guardar en un archivo tmp
  4. Leer + establecer variables de archivo env desde archivo
  5. Use docker-compose para fusionar los tres archivos juntos
  6. Implementar archivo combinado

Para aquellos de ustedes que anhelan extends en componer más de 3 archivos, acabo de poner mis manos en una herramienta llamada baclin . baclin linealiza dichas directivas, reemplazando recursivamente todas las directivas extends por su contenido. Este es un software alfa, el código es parte de mi maquinaria, ya que actualmente estoy escribiendo código para admitir el modo Swarm y la implementación de pilas. Los binarios de la plataforma de una versión anterior de baclin están disponibles aquí . Informe cualquier comentario o problema aquí .

¡Esto es realmente confuso!
Al leer el documento para obtener la última versión de la ventana acoplable ( v17.09 ) y también el documento de versión v17.06 esta función debería estar disponible.

$ head -n1 docker-compose.yml
version: '3'

Pero compose up rinde

ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.admin_application: 'extends'

cuando se utiliza la palabra clave extends .
Además, no puedo encontrar nada sobre la eliminación de extends en el registro compose cambios compose .

¡¿Ahora cuál es ?!
Información crucial como esta no debería ser difícil de encontrar u oculta dentro de algún oscuro problema de github.


$ docker --version
Docker version 17.09.0-ce, build afdb6d4

$ docker-compose --version
docker-compose version 1.16.1, build 6d1ac21

@jottr , ver documentos :

La palabra clave extiende es compatible con formatos de archivo Compose anteriores hasta la versión 2.1 del archivo Compose (consulte las extensiones en v1 y las extensiones en v2), pero no es compatible con la versión 3.x de Compose.

Entonces, si desea usar extends , debe quedarse hasta version: '2.1' .

Mi error. Aún debería estar en la parte superior del documento con una señal de advertencia de desaprobación roja.

Mi error. Aún debería estar en la parte superior del documento con una señal de advertencia de desaprobación roja.

@jottr Solo usa Github para crear un problema separado para eso o incluso crea un PR para eso. Acabo de crear el problema aquí: https://github.com/docker/docker.github.io/issues/5340

En mi caso, tengo el docker-compose-override.yml siguiente manera:
yaml version: "3.4" services: common: extra_hosts: - "host1:172.28.5.1" - "host2172.28.5.2" - "host3:172.28.5.3" networks: default: external: name: "common-network"
Y tengo varios otros archivos docker-compose.yml que necesitan compartir la red y extra_hosts. ¿Cómo hacer esto usando la función sin extensión?

yaml version: "3.4" services: mongo: image: "mongo" container_name: "mongo" hostname: "mongo" volumes: - "/opt/docker/mongo/default.conf:/usr/local/etc/mongo/mongod.conf" - /opt/data/mongo:/data/db" ports: - "27017:27017" command: "mongod --config /usr/local/etc/mongo/mongod.conf" networks: default: ipv4_address: "172.28.5.4"
Sería genial si docker-compose soportara el ancla yaml y las referencias entre diferentes archivos. Tal vez, aplicando ancla y referencias después de fusionar archivos.
Por ejemplo:
yaml version: "3.4" services: common: &common extra_hosts: ... networks: ...
yaml version: "3.4" services: mongo: <<: *common image: "mongo" container_name: "mongo" ...
El resultado debería ser:
yaml version: "3.4" services: mongo: image: "mongo" container_name: "mongo" extra_hosts: // EXTRA HOSTS HERE networks: ...

@ sandro-csimas esto es posible con: https://docs.docker.com/compose/compose-file/#extension -fields
@ shin- ¿podría cerrarse este boleto?

@rdxmb No lo creo. Por lo que puedo ver, no se puede extender desde otro archivo docker-compose

¿Estoy en lo cierto al pensar que esto es un problema para https://github.com/docker/compose/issues ?

Algo de depuración:

# cat docker-compose.yml 
version: "3.4"
services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR 

x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

Esto esta trabajando con
docker stack deploy -c docker-compose.yml test

Al usar docker-compose:

# docker-compose up 
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./docker-compose.yml", line 4, column 10

Cambiando el archivo yml a:

version: "3.4"

x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR

también funciona con docker-compose.

Así que pensé que esto también debería funcionar con varios archivos, que no es el caso:

# docker-compose -f compose-services.yml -f compose-default.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./compose-services.yml", line 5, column 10
t# docker-compose -f compose-default.yml -f compose-services.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./compose-services.yml", line 5, column 10
# cat compose-services.yml 
version: "3.4"

services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR 

# cat compose-default.yml 
x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

Sin embargo, por supuesto, fusionar esto es posible con un simple uso de cat :

# cat compose-default.yml compose-services.yml > docker-compose.yml && docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Creating network "test_default" with the default driver
Creating test_foo-bar_1 ... 
Creating test_foo-not-bar_1 ... 
Creating test_foo-bar_1
Creating test_foo-bar_1 ... done

Ejecutando en xenial con las versiones:

# docker --version
Docker version 17.11.0-ce, build 1caf76c
# docker-compose --version
docker-compose version 1.17.0, build ac53b73

@rdxmb , ¡gracias!
Así que debería ir combinando archivos de redacción usando el comando "cat" y ejecutando el archivo final.

También utilizo docker-compose config para hacer esto. Un ejemplo de configuraciones específicas del entorno:

Esto lo ejecuta la canalización de CI: docker-compose -f docker-compose.yml -f docker-compose.override.prod.yml config > docker-compose.prod.yml y luego uso docker stack deploy -c .\docker-compose.prod.yml my-stack

Vote por esto, la extensión es muy útil para v3.

Lo usé mucho con v2, ¡muy útil de hecho!
+1

Me encantaría ver el soporte de extends en v3. Ayudaría a SECAR mucho mi archivo docker-compose.yml .

Ha pasado casi un año desde que se presentó este problema y es realmente obvio que muchas personas necesitan esta función. Sin embargo, no he leído que un desarrollador de Docker responda a esta solicitud, ni una explicación de por qué no se incluyó en docker-compose v3 antes del lanzamiento.

Triste estado del software si ni siquiera podemos comunicarnos o mantener funciones para nuestros clientes que confían en una nueva tecnología.

Una posible interpretación (y tal vez también un resumen del hilo actual) de la situación es así:

  • Los anclajes / referencias YAML más los campos de extensión de 3.4 logran casi lo mismo.
  • se puede hacer que varios archivos funcionen. Vea el cat simple y el enfoque avanzado en este hilo. El comentario de enfoque simple muestra un problema de docker-compose cargando múltiples archivos hacia el final (¿alguien ha creado un problema para eso?). Si eso se solucionó en docker-compose, ni siquiera necesitaría la fusión del archivo. Entonces, para mí, las personas que desean compatibilidad con múltiples archivos deberían continuar en docker / compose / issues como propuso @rdxmb .
  • Se consideró traer de vuelta extends (ver eventos del proyecto de GitHub , buena transparencia aquí del equipo de Docker, ¡gracias!) Y puede interpretar el resultado como "hay muchas otras cosas que son estratégicamente más importantes para ellos", pero puede todavía escribo una solicitud de extracción para extends , supongo.

Para mí, ese es un punto de vista perfectamente comprensible.

@aCandidMind estuvo de acuerdo.

En mi humilde opinión, aunque los enfoques mencionados por @aCandidMind funcionan, agregan complejidad al mecanismo más simple y limpio proporcionado por extends .
Tal vez sea yo, pero mover una configuración de extensión moderadamente compleja a campos de extensión se vuelve mucho más difícil de leer y mantener.
Después de leer muchos comentarios y publicaciones, todavía no me queda claro por qué se eliminó la extensión y cuáles son las ventajas de esta regresión en las capacidades.

Es posible que con un poco de magia bash ponga un repositorio de prueba para que puedas probarlo tú mismo.

Simplemente estructura tu comando stack deploy esta manera:

docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config) <stackname>

@tylerbuchea : el único inconveniente de esa magia bash es que podrías obtener un WARNING: Some services (<service-name(s)>) use the '<key>' key, which will be ignored. Compose does not support '<key>' configuration . Esto puede causar cierta confusión. Pero bueno, funciona 👍

@dnmgns ¡tienes razón! Gracias por señalar eso. Como dijo @joaocc , nada va a superar al soporte nativo, pero la solución que mencioné anteriormente es la mejor que pude encontrar dado que no hay otras dependencias que no sean bash.

@tylerbuchea Una forma sucia es simplemente redirigir stderr a / dev / null :)
docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config 2> /dev/null) <stackname>

No es ninguna vergüenza 😄

Creo que la documentación debería ser más explícita sobre esta confusión en torno a extend .
La descripción de extend redirige al usuario a los documentos de cómo actualizar, y los documentos de cómo actualizar apuntan a la descripción de extend para obtener más información. Esto no es lo suficientemente útil: como usuario, esperaría ayuda sobre cómo lidiar con todo este problema, qué opciones tengo y qué debo considerar. Estoy muy seguro de que había una idea clara detrás de la decisión de eliminar extend de v3.

Ver:
https://docs.docker.com/compose/extends/#extending -services
https://docs.docker.com/compose/compose-file/compose-versioning/#upgrading

Con respecto a @tylerbuchea, una gran solución basada en bash de una sola línea,
lamentablemente, no admite algunas funciones avanzadas de la pila de Docker:

WARNING: Some services (web) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
WARNING: Some services (web) use the 'configs' key, which will be ignored. Compose does not support 'configs' configuration - use `docker stack deploy` to deploy to a swarm.

No es que, dado que https://github.com/docker/cli/pull/569 se fusionó, a partir de 18.03, docker stack deploy admitirá la fusión de varios archivos de redacción en uno. No reemplaza completamente la clave extends del formato de archivo de composición v2, pero es de esperar que cubra muchos más casos de uso 👼

Mi propia solución fue usar yq (se puede combinar en una sola línea si se usa Bash):

yq merge --overwrite docker-stack.yml docker-stack.preprod.yml > merged-docker-stack.yml
docker stack deploy -c merged-docker-stack.yml preprod

@ Lucas-C son solo advertencias, la salida aún incluirá sus claves deploy y config . Puede verificar esto si ejecuta docker-compose -f docker/prod.yml -f docker/dev.yml config

Es para componer archivos v3.4 y superiores. Admite referencias cruzadas de Yaml (parcial). Terminé con este script zsh alias / perl:

alias regen=$'perl -MFile::Slurp=read_file -MYAML=Load,Dump -MHash::Merge::Simple=merge -E \'
  local $YAML::QuoteNumericStrings = 1;
  $n=read_file("/data/docker-compose.yml");
  $s=Dump(merge(map{Load($n.read_file($_))}@ARGV));
  local $/ = undef;
  $s =~ s/\\bno\\b/"no"/g;
  say $s;
  \' $(find /data -mindepth 2 -maxdepth 4 -name docker-compose.yml) >! /data/x-docker-compose.yml'
regen
export COMPOSE_FILE=/data/x-docker-compose.yml
  1. leer /data/docker-compose.yml con la parte común.
  2. encuentre todos los archivos docker compose de forma recursiva (por ejemplo, hay alrededor de 40 contenedores / archivos docker-compose.yml diferentes en este proyecto)
  3. anteponga cada docker-compose.yml con el contenido /data/docker-compose.yml
  4. unir
  5. guardar el resultado en /data/x-docker-compose.yml

Ventajas : perl es una herramienta común, todos los módulos de perl también, la generación es rápida.
Contras : Odio los trucos, pero no hay otra forma de DRY. La composición final de la ventana acoplable es de unas 900 líneas. ¿De verdad quieres que lo soporte como un solo archivo desde el principio? Es una pena tener la ventana acoplable binaria envuelta con python docker-compose envuelta con perl hack.

¿Cómo se puede eliminar una función como se extiende? Eso parece una característica fundamental.

El uso de docker-compose config canalizado a la opción de entrada estándar de docker stack deploy -c - ha resuelto el problema:

docker-compose -f docker-compose.yml \
               -f docker-compose.extended.yml \
               config \
| docker stack deploy -c - my-stack

No he probado esto, pero también me di cuenta de esto en la documentación docker stack deploy :

Si su configuración está dividida entre varios archivos Compose, por ejemplo, una configuración base y anulaciones específicas del entorno, puede proporcionar varios indicadores --compose-file .

Con esto como ejemplo:

docker stack deploy --compose-file docker-compose.yml -f docker-compose.prod.yml vossibility

https://docs.docker.com/engine/reference/commandline/stack_deploy/#compose -file

¿Está documentada en alguna parte la justificación de la eliminación de extends ? No parece estar explicado en los documentos oficiales, por ejemplo, aquí: https://docs.docker.com/compose/extends/#extending -services
Si los usuarios pudieran entender el fundamento, entonces los usuarios podrían desarrollar una mejor idea de cómo responder a la eliminación. Gracias.

@ shaun-blake Terminé usando varios archivos de redacción. Ese parece ser el enfoque que usa la gente. En lugar de herencia, es más como una mezcla. Al compilar o ejecutar, copio la plantilla yaml del entorno correcto en docker-compose.override.yml.

Varios archivos de composición de Docker (por ejemplo: base.yml , local.yml , prod.yml ) no permiten que el servicio use anclajes YAML de otros archivos, por lo que las definiciones de servicio factorizadas no se pueden definir entre varios archivos yml .
Tenga en cuenta que este problema es el número 13 más comentado : https://github.com/moby/moby/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc y el tercero más me gusta .

Si los usuarios pudieran entender el fundamento, entonces los usuarios podrían desarrollar una mejor idea de cómo responder a la eliminación. Gracias.

+1 en la documentación sobre la justificación para eliminar extends en primer lugar ...

Todavía no se extiende después de casi 1 año y medio después. Vamos, desarrolladores, no eliminen algo sin dar una alternativa.

Lo hicieron, ofrecen una alternativa llamada composición. Por favor lea mi respuesta en el hilo.

-Filippo

El 30 de julio de 2018, a las 09:41, Xiaohui Liu [email protected] escribió:

Todavía no se extiende después de casi 1 año y medio después. Vamos, desarrolladores, no eliminen algo sin dar una alternativa.

-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en GitHub https://github.com/moby/moby/issues/31101#issuecomment-408790200 , o silencie el hilo https://github.com/notifications/unsubscribe-auth/AAS_0AOynjpfVnVo4ZqciMbmjBmkcTQb4ksga5upLs .

@dedalozzo , "en el hilo" ==?

Por favor, vea mi comentario aquí:

https://github.com/moby/moby/issues/31101#issuecomment -329527600 https://github.com/moby/moby/issues/31101#issuecomment-329527600

Básicamente, debe usar una cadena de archivos .yml para anular o cambiar la configuración de sus contenedores.

Lea "Especificación de varios archivos de redacción"

Puede proporcionar varios archivos de configuración -f. Cuando proporciona varios archivos, Compose los combina en una única configuración. Compose crea la configuración en el orden en que proporcionas los archivos. Los archivos posteriores anulan y agregan a sus predecesores.

https://docs.docker.com/compose/reference/overview/ https://docs.docker.com/compose/reference/overview/

Este enfoque utiliza la composición sobre la herencia para obtener, más o menos, el mismo resultado.

El 30 de julio de 2018, a las 15:23, Serban Teodorescu [email protected] escribió:

@dedalozzo https://github.com/dedalozzo , "en el hilo" ==?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub https://github.com/moby/moby/issues/31101#issuecomment-408880809 , o silencie el hilo https://github.com/notifications/unsubscribe-auth/AAS_0FZO30NplqHRid_Id8VBOJW7nk5Iks5uLx4 .

¿No podríamos recuperar la misma extensibilidad si combinamos
campos de extensión yaml (componen 2.1 + / 3.4 +)
con permitir que esos campos x- hagan referencia a otros archivos ?

Por lo tanto, podríamos permitir que una lista raíz include especifique archivos para cargar.
se colocarían en un x-include y se utilizarían instantáneamente a través de anclajes YAML estándar y fusión.



Redacción actual v2.1 +
# /docker-compose.yml
version: '2.1'

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    extends:
      file: reverse_proxy/docker-compose.yml
      service: proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    extends:
      file: reverse_proxy/docker-compose.yml
      service: proxy
    restart: 'always'
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    extends:
      file: webservice/docker-compose.yml
      service: app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    extends:
      file: webservice/docker-compose.yml
      service: app
    restart: 'no'
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

# /proxy/docker-compose.yml
version: '2.1'
services:
  proxy:
    build: ./
    volumes:
      - /certs:/certs:ro
# /webservice/docker-compose.yml
version: '2.1'
services:
  app:
    build:
      context: ./folder
      args:
        LINUX_VERSION: 20.s
        LINUX_FLAVOR: dash
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - bootstrap.memory_lock=true
    ulimits:
      memlock:
        soft: -1
        hard: -1




Idea de compose v3.X
# /proxy/docker-compose.yml
version: '3.9'
services:
  proxy:
    &proxy
    build: ./
    volumes:
      - /certs:/certs:ro
# /webservice/docker-compose.yml
version: '3.9'
services:
  app:
    &app
    build:
      context: ./folder
      args:
        LINUX_VERSION: 20.s
        LINUX_FLAVOR: dash
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - bootstrap.memory_lock=true
    ulimits:
      memlock:
        soft: -1
        hard: -1
# /docker-compose.yml
version: '3.9'
include:
  - /proxy/docker-compose.yml
  - /webservice/docker-compose.yml

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    << : *proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    restart: 'always'
    << : *proxy
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    << : *app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    restart: 'no'
    extends:
      file: web1/docker-compose.yml
      service: app
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx




Diferencia
@@ /proxy/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
 services:
   proxy:
+    &proxy
     build: ./
     volumes:
       - /certs:/certs:ro
 ```

 ```diff
 @@ /webservice/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
 services:
   app:
+    &app
     build:
       context: ./folder
       args:
         LINUX_VERSION: 20.s
         LINUX_FLAVOR: dash
     environment:
       - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
       - bootstrap.memory_lock=true
     ulimits:
       memlock:
         soft: -1
         hard: -1
 ```

 ```diff
 @@ /docker-compose.yml @@
-version: '2.1'
+version: '3.9'
+include:
+  - /proxy/docker-compose.yml
+  - /webservice/docker-compose.yml

 volumes:
   nginx_file_sockets:
     external: false
     driver: local

 services:
   reverse_proxy:
-    extends:
-      file: reverse_proxy/docker-compose.yml
-      service: proxy
+    << : *proxy
     restart: 'always'
     ports:
       - "80:80"
       - "443:443"
     volumes:
       - nginx_file_sockets:/sockets/nginx

   reverse_proxy_test:
-    extends:
-      file: reverse_proxy/docker-compose.yml
-      service: proxy
+    << : *proxy
     restart: 'no'
     ports:
       - "8080:80"
       - "8443:443"
     volumes:
       - nginx_file_sockets:/sockets/nginx

   web:
-    extends:
-      file: webservice/docker-compose.yml
-      service: app
+    << : *app
     restart: 'always'
     environment:
       ENVIRONMENT: 'production'
       DB_USER: ${WEB1_DB_USER}
       DB_PASSWORD: ${WEB1_DB_PASS}
     volumes:
       - nginx_file_sockets:/sockets/nginx

   web_staging:
-    extends:
-      file: webservice/docker-compose.yml
-      service: app
+    << : *app
     restart: 'no'
     environment:
       ENVIRONMENT: 'staging'
       DB_USER: ${WEB1_DB_USER}
       DB_PASSWORD: ${WEB1_DB_PASS}
     volumes:
       - nginx_file_sockets:/sockets/nginx
 ```
<hr>
Resulting in the final version, which should be already yaml parsable:

```yml
# /docker-compose.yml
version: '3.9'
#include:
#  - /proxy/docker-compose.yml
#  - /webservice/docker-compose.yml
x-include:
  /proxy/docker-compose.yml:
    version: '3.9'
    services:
      proxy:
        &proxy
        build: ./
        volumes:
          - /certs:/certs:ro
  /webservice/docker-compose.yml:
    version: '3.9'
    services:
      app:
        &app
        build:
          context: ./folder
          args:
            LINUX_VERSION: 20.s
            LINUX_FLAVOR: dash
        environment:
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
          - bootstrap.memory_lock=true
        ulimits:
          memlock:
            soft: -1
            hard: -1

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    << : *proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    << : *proxy
    restart: 'no'
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    << : *app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    << : *app
    restart: 'no'
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

AFAIK, esa es una función YAML, integrada en la propia especificación de idioma, para evitar la repetición de partes en el mismo archivo. Cuando se utilizan diferentes archivos, eso es básicamente imposible.

Debería proponer esa característica a la propia especificación YAML.

Esta discusión se reduce a:

  • ¿Cómo docker-compose -f file.yml es mucho mejor que docker-compose -f file.yml -f file_extension.yml ?
  • O: cableado en el nivel de comando _vs_ cableado en el nivel de archivo.

Solo cuando se trabaja en la línea de comandos, el inconveniente se vuelve notable. Tenemos que reconocer eso por un segundo. Todo lo demás es programable, de todos modos.

Si ese es el argumento real, entonces docker-compose up service tiene mejor semántica que docker-compose -f service.yml up : defina todo lo necesario para el desarrollo local (también conocido como en la línea de comando) en docker-compose.override.yml .

La semántica dada es muy limpia y bien pensada. Adoptar service.yml _ para el uso de la línea de comando_ probablemente signifique reducir la UX. Hay otro argumento: si bien está claro a primera vista, lo que es un docker-compose.yml , un service.yml puede ser cualquier cosa, realmente cualquier cosa.

Descargo de responsabilidad: una opinión provocativa. : wink: No tomé en cuenta todos los casos de uso posibles ...

Después de esta prolongada discusión, no estoy seguro de si alguna vez lo logrará. En mi humilde opinión, la extensión fue genial y debe haber sido al menos cuidadosamente desaprobada y luego discutida en lugar de simplemente descartarla.

Creo que una cosa que podríamos hacer es mejorar la historia de la documentación sobre v2 vs v3. Muchos asumen que v3 reemplazó a v2, pero eso no es del todo cierto. Ambos reciben nuevas funciones que se centran en sus casos de uso. Este problema de GH se inició para que pudiéramos tener la discusión sobre las características futuras necesarias para pasar de docker-compose a Swarm, y cómo mejorar los documentos para usar docker-compose, el formato de archivo de composición y las pilas de Swarm juntas. Extiende todavía funciona muy bien en la versión actualizada v2.4. Con suerte, puedo ayudar a ofrecer información sobre las soluciones que tenemos hoy:

v2: solo para docker-compose cli. Flujo de trabajo de desarrollo centrado en una sola máquina y motor. También es bueno para flujos de trabajo de construcción / prueba de CI. Esta rama de la versión recibió nuevas características tan recientes como diciembre de 2017 en v17.12

v3: Ideal para pilas Swarm / Kube, con conceptos de múltiples nodos y mantiene la compatibilidad con la mayoría de las funciones de cli de composición de docker.

Si no usa las pilas Swarm o Docker Enterprise Kubernetes, no hay razón para usar v3 . Siga con la v2.4 y obtendrá todas las funciones de cli de docker-compose, incluidas las extensiones, dependencias, campos de extensión e incluso dependencias con comprobaciones de estado (para evitar los scripts de espera).

v3 se creó para intentar fusionar las características de un mundo cli de composición acoplable de un solo motor con un mundo de clúster de múltiples nodos. No todas las funciones de la versión 2 (como depende_en) tienen sentido en un clúster. Otras características (como extender) simplemente no se han incorporado a v3, probablemente porque antes de que existiera v3, todo el código estaba en Python de composición de docker, y para que v3.0 fuera compatible con Swarm, tuvieron que reescribirlo en docker cli Go, y ahora lo están escribiendo nuevamente en el demonio del motor para eventualmente hacer una API de pilas de Swarm, que aún no existe.

Para aquellos que son nuevos en este tema, también tengan en cuenta gran parte del trabajo que se ha realizado para resolver varios problemas de configuración, plantillas y flujo de trabajo en equipo desde la versión 3.0:

Los documentos en https://docs.docker.com/compose/extends/#extending -services deben enfatizar en rojo el hecho de que la palabra clave extiende se elimina en v3, ya que es más importante que solo una _note_.
Migré y revisé los documentos para ver por qué ya no funcionaba, luego seguí varios problemas cerrados antes de terminar aquí, luego volví a los documentos originales y noté la redacción.

La palabra clave extiende es compatible con formatos de archivo Compose anteriores hasta la versión 2.1 del archivo Compose (consulte las extensiones en v1 y las extensiones en v2), pero no es compatible con la versión 3.x de Compose.

Podría reformularse como:

La palabra clave extiende se ha eliminado en la versión 3.x de Compose, pero aún se admite en formatos de archivo de Compose anteriores hasta la versión 2.1 de archivo de Compose (consulte las extensiones en v1 y las extensiones en v2).

Es una pequeña diferencia, pero una que es fácil de pasar por alto al hojear documentos.

@krisrp PR comenzó ^^^

Gracias @BretFisher

¿Hay algún plan para quizás cambiar el nombre de v2 a "versión: docker-cli" y v3 a "versión: swarm / kube"?
Tendría más sentido diferenciarlos así, considerando cómo v3 reemplaza a v2 en la mayoría de los otros esquemas de control de versiones. En la actualidad, ambos se mantienen y divergen, por lo que, a menos que me equivoque, parece que ambos estarán presentes por un tiempo.

@krisrp Por el contrario, la razón para incrementar un número de versión principal es señalar la divergencia en la compatibilidad.

@ cpuguy83 No estaba insinuando lo contrario. Disculpas por no ser más claro o explícito.
IIRC Gnome 2 & 3 también tuvo esta confusión hace años cuando se mantuvieron las bifurcaciones independientes de cada uno.

No quiero descarrilar este hilo para discutir la semántica del control de versiones (mal juego de palabras), así que lo dejaré así. La publicación de

@ shin- @ cpuguy83 Mirando este tema más de un año después, ¿cuál es el motivo para no volver a agregarlo en la versión 3?

No pude encontrar mucho al respecto, aparte de "podríamos hacerlo de manera diferente" (pero no se ofrece una solución mejor)
¿Existe alguna limitación técnica? ¿O simplemente una falta de solicitud de extracción?

Después de todo, mis archivos de composición 2.1 todavía funcionan bien.

No solo esto, sino que el registro de cambios dice "esto se ha eliminado, consulte 'cómo actualizar' para obtener más detalles". Miro "cómo actualizar" para, ya sabes, detalles sobre cómo actualizar, y lo que dice es "ver 'ampliar servicios' para obtener más detalles". Voy a "extender servicios" pensando que finalmente veré una manera de extender mis archivos, solo para ver "esto se ha eliminado, consulte el registro de cambios para obtener más detalles".

En este punto, esto parece una broma cruel que está jugando el escritor de documentación.

En última instancia, el formato de "pila" no se controla aquí y es parte de la CLI de Docker.

Personalmente, no sé la razón por la que se excluyó de la versión 3 ... Tampoco creo que haya visto a nadie intentar agregarlo.
Podría ser mejor mencionar esto en docker / cli ... tal vez incluso solo un PR con un cambio de documento de alto nivel que actúa como si la característica estuviera allí para que pueda discutirse y la implementación se pueda agregar una vez que se apruebe el diseño .

Básicamente, si alguien lo quiere, haz un PR. Sugiero el cambio de documento solo para asegurarse de no perder mucho tiempo en caso de que sea rechazado ... ya que nuevamente no estoy seguro de por qué se omitió de la v3.

Lo mismo que arriba. Esperando a que esto se resuelva antes de usar docker-compose nuevamente.

+1, por favor arregle esto, tenemos archivos de redacción basados ​​en extensiones y no podemos usar componer para swarm debido a eso.

+1 para la función de extensión

¿Alguna noticia sobre esto?

Sigo esperando por ello

Aquí igual. Todavía esperando.

¿Cualquier actualización?

¿Alguna vez se dio una razón de por qué se quitó?

El lunes 5 de agosto de 2019 a las 11:10 Jaykishan, [email protected] escribió:

¿Cualquier actualización?

-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/31101?email_source=notifications&email_token=ABOE6GA4CXY6ESMZMTDSFGDQC74CZA5CNFSM4DANZGS2YY3PNVWWK3TUL52HS4DFVREXG43VWWK3TUL52HS4DFVREXG43KNDMVNW3com
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/ABOE6GCEFFJ3SOLDWRWX2IDQC74CZANCNFSM4DANZGSQ
.

¿Cualquier actualización?

así que ... son casi 3 años ...
pero todavía tengo la esperanza de que aterrice: D

Es necesario que exista algún tipo de alternativa a las extensiones si no regresa. ¿Por qué no permitir los servicios abstractos? El formato de archivo sería plano y todas las declaraciones de servicio estarían en un solo archivo. Puede usar servicios abstractos junto con la capacidad de yaml para agregar alias para un nodo (a través de un & ) reutilizar esos alias a través del operador <<: .

¡¡Por qué 3 años !! parece que estás trabajando y enfocándote en cosas que a nadie le importan

¿Algún avance en esto?

Esto es patético. Terraform usa la composición, por lo que es factible, ¿por qué componer no es capaz de seguir esta buena práctica de diseño?
Composición de los módulos Terraform
Mejores prácticas de Terraform

"patético", agradable.

@ Cristian-Malinescu Adelante, impleméntalo por favor.
Este es un software gratuito y de código abierto.

En lugar de quejarse como todos los demás en este chat.
Eso simplemente no agrega ningún valor aquí, de verdad.
Como se dijo varias veces, nadie quería implementar esto hasta ahora,
así que es solo un problema que alguien más debería solucionar k, gracias.

@luckydonald Gracias por alejar a @ Cristian-Malinescu con una respuesta fácil / pasivo-agresiva, es, como siempre, no ayudar. @ Cristian-Malinescu Es factible como ya se hizo antes, pero eliminado, debe (espero) haber una razón. ¿Hay alguien en este hilo realmente en el equipo de docker-compose para que pueda arrojar luz sobre el ¿importar?

Se ha examinado el hilo y se ha mencionado el aprovechamiento de la funcionalidad YAML admitida.

Pensé que este ejemplo podría ayudar.

@nomasprime ¡ gracias por ese hallazgo! Estaba decidiendo entre v2 y v3 para mi proyecto, y esto resolvió el gran dilema en este hilo. Sorprende que estas soluciones alternativas no se mencionen en los documentos oficiales para la función de extensión de servicios.

Bien, parece una buena oportunidad para usar el enlace Request docs changes en la barra de navegación derecha de la página de documentos.

@nomasprime Sí, esa idea estaba en este hilo antes.

Si eso pudiera combinarse con un mecanismo de carga de archivos para otros archivos yml, eso es todo lo que realmente se necesita para tener toda la antigua funcionalidad depends .

Consulte más arriba, por ejemplo, https://github.com/moby/moby/issues/31101#issuecomment -413323610

No sería muy _leíble_, pero al menos _posible_.

@nomasprime ¡ gracias por ese hallazgo! Estaba decidiendo entre v2 y v3 para mi proyecto, y esto resolvió el gran dilema en este hilo.

@arseniybanayev El artículo sobre el medio solo habla de v3, pero las versiones más recientes de v2 también admiten anclas y campos de extensión . En mi caso, elijo v2 (2.4 más específicamente) porque uso docker-compose y no swarm (y v3 no admite algunas características de v2 como limitar la memoria del contenedor )

y v3 no admite algunas características de v2 como limitar la memoria del contenedor

v3 admite la limitación de memoria, pero el campo está por debajo de deploy -> resources -> limits https://docs.docker.com/compose/compose-file/#resources

@thaJeztah Quiero decir, por docker-compose (porque no estoy usando swarm en el proyecto al que me refería en mi comentario anterior). El despliegue del IIRC es solo para enjambres, ¿no es así?

¿Tendría sentido hacer una configuración separada para swarm y local? Parece que estos dos están en conflicto entre sí. Es comprensible que a Docker le gustaría que aumentara el uso de enjambres, pero mucha gente solo usa componer para el desarrollo local.

Por mi parte, nunca he usado contenedores swarm and run en producción con ECS, k8s o GAE.

La mayoría de las opciones deben ser traducibles / utilizables tanto para los servicios swarm / kubernetes como para los contenedores implementados a través de compose. Tendría que verificar por qué los límites de memory no serían aplicables para docker-compose

Todavía me falta la función de extensión, pero para mi caso de uso principal cambié a varios archivos de composición de Docker a través de COMPOSE_FILE env. Lo uso principalmente para usar la misma base docker-compose.yml para dev y prod con diferentes contraseñas o configuraciones.

ejemplo:

  • en dev: export COMPOSE_FILE= docker-compose.yml` # predeterminado
  • en prod: export COMPOSE_FILE= docker-compose. yml: docker-compose.prod.yml `# usa ambos archivos yaml

En docker-compose.prod.yml simplemente sobrescribo las variables de entorno con las contraseñas de prod.

Esta configuración es simple y no necesito agregar siempre múltiples "-f" al comando docker-compose . Solo necesito configurar COMPOSE_FILE env var diferente en la computadora dev y el servidor y git ignora el archivo docker-compose.prod.yml.

Todavía esperando :)

He estado usando esto como una forma de extender:

docker-compose \
  -f ./docker/base.yml \
  -f ./docker/extended.yml \
  up

Pero extender en el archivo sería mejor, no es necesario un script bash adicional.

También he estado usando esto para extender dinámicamente desde el script bash:

extended_docker_compose="
  version: '3.5'
  services:
    my-service:
      restart: always
"

echo "$extended_docker_compose" | docker-compose \
  -f ./docker/base.yml \
  -f /dev/stdin \
  up

@ dave-dm ¡esas son anulaciones simples y antiguas!

Creo que este es un caso de uso válido potencial para extensiones

https://github.com/NerdsvilleCEO/devtools/blob/master/doctl/docker-compose.yml#L10

Tengo un contenedor docker-compose que uso para un env de servicios https://github.com/nowakowskir/docker-compose-wrapper

EDITAR: Otro posible caso de uso es que alguien tiene una pila LAMP / LEMP y quiere extender esos servicios para usarlos con un servicio específico como wordpress

Seguimos esperando desde 2017 mientras exploramos las alternativas de composición de Docker.

@nomasprime Sí, esa idea estaba en este hilo antes.

Si eso pudiera combinarse con un mecanismo de carga de archivos para otros archivos yml, eso es todo lo que realmente se necesita para tener toda la antigua funcionalidad depends .

Vea arriba, por ejemplo, # 31101 (comentario)

No sería muy _leíble_, pero al menos _posible_.

@luckydonald gracias por señalar. Curiosamente, no hay una funcionalidad de inclusión de YAML incorporada , sin duda resolvería muchos problemas.

Sin embargo, parece que sería bastante fácil implementar una solución de terceros, así que no estoy seguro de por qué no se ha trasladado a la v3 🤷‍♂

Un pequeño recordatorio de que a mucha gente le gustaría esta función :)

¿Cuál es la razón para no portarlo a v3 por cierto?

Lo olvido, pero ¿hay una razón real por la que se lo quitaron?

El miércoles 6 de mayo de 2020 a las 23:14, Julien Marechal, [email protected] escribió:

Un pequeño recordatorio de que a mucha gente le gustaría esta función :)

-
Estás recibiendo esto porque hiciste un comentario.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/31101#issuecomment-624919070 , o
darse de baja
https://github.com/notifications/unsubscribe-auth/ABOE6GGDIVGATP734YJA4UTRQHOLJANCNFSM4DANZGSQ
.

La forma en que los anclajes yaml manejan este caso de uso es un poco inconveniente en comparación con extend . Su poder, en mi opinión, provino en gran parte de la fusión recursiva de elementos. Los anclajes te llevan quizás al 75% del camino hasta allí; no fusionan yaml de forma recursiva; toda su fusión ocurre en el nivel superior. Hacer referencia a una plantilla de servicio anclado y luego redefinir el bloque environment resultará en sobrescribir el bloque de entorno del servicio anclado en lugar de fusionarlo. Deberá anclar y hacer referencia a cada diccionario en un árbol recursivo de diccionarios para que coincida con el comportamiento de la palabra clave extend .

Un ejemplo:

# anchors for the service, environment, deploy, and deploy.placement blocks
# you'll need an anchor for every dict that you want to merge into
x-common-app: &common-app
  image: app:1.0
  environment: &common-app-environment
    common_option: a
    overwrite_option: b
  deploy: &common-app-deploy
    max-replicas-per-host: 3
    placement: &common-app-deploy-placement
      constraints:
        - 'node.labels.app_host==true'

services:
  myapp: << *common-app
    environment: << *common-app-environment
      foo: bar
      baz: xyzzy
      overwrite_option: quz
    deploy: << *common-app-deploy
      replicas: 15
      placement: << *common-app-deploy-placement
        preferences:
          - spread: node.labels.region

# The above yields the following:
services:
  myapp:
    image: app:1.0
    environment:
      common_option: a
      overwrite_option: quz
      foo: bar
      baz: xyzzy
    deploy:
      replicas: 15
      max-replicas-per-host: 3
      placement:
        constraints:
          - 'node.labels.app_host==true'
        preferences:
          - spread: node.labels.region

Puede que no parezca tan molesto en este ejemplo, pero se vuelve molesto y menos legible si está creando plantillas para múltiples (10+) servicios de un bloque de extensión.

En mi opinión, un escenario ideal es una combinación del enfoque de anclaje yaml y el enfoque extend : permitir extend ing solo desde un bloque de campo de extensión prefijado x- nivel superior, con las características de fusión más inteligentes.

En mi organización, encontramos anclajes yaml un poco sintácticamente descuidados, por lo que básicamente reimplementamos la función extend en un script externo de Python. Eso funciona para nosotros, pero es una forma poco convincente de tener que lidiar con algo. De manera similar, hemos tenido que crear nuestras propias herramientas externas para lidiar con la eliminación de depends_on para las pilas v3 / Swarm.

He hecho mucho gitlab CI YAML últimamente. Tiene exactamente estas características, que son tan agradables para lograr plantillas y configuraciones finales legibles y manejables:

  • Puede incluir otros archivos YAML (bueno para plantillas)
  • Puede extender (incluso a través de proyectos / usando recursos remotos a través de https). La documentación ampliada describe exactamente lo que @ a-abella describe para el formato de redacción.
  • También puedes "esconderte" para que no te consideren algo real. En formato de redacción es x- , en gitlab CI es un . inicial en su lugar.

Este es el conjunto exacto de características que hace que estos archivos sean soportables.

Llegué a este problema desde los documentos de la ventana acoplable, en mi caso quería crear una plantilla de mi configuración docker-compose y, como 'solución alternativa', seguí los consejos anteriores y decidí buscar un programa de plantillas existente. No recuperaré esas horas, así que estoy detallando un poco de lo que encontré aquí, independientemente de cualquier discusión sobre esta solicitud de función real, sin embargo, es posible que los involucrados sientan el uso de un sistema de plantillas basado en YAML para generar un archivo de redacción en lugar de integrar esta función en docker-compose sí mismo podría ser más apropiado en términos de encapsulación y elección de la herramienta adecuada para el trabajo.

Para algún contexto, estoy usando un proxy inverso básico con Let's Encrypt y varios contenedores de aplicaciones (Nextcloud por ahora, uno para mí y algunos separados para amigos); en este caso, quería hacer una plantilla de los contenedores de Nextcloud, así que que evito errores y duplicaciones con pulsaciones de teclas para configuraciones muy similares. Los siguientes paquetes fueron los que probé:

ytt parece muy completo y es la única opción para usar YAML de forma nativa. Parecía poderosa y la herramienta adecuada para el trabajo, y usa Starlark, un superconjunto de Python, directamente dentro del archivo YAML para realizar el procesamiento. Sin embargo, después de poco tiempo, la plantilla se volvió muy desordenada y la basura de fragmentos de código y fragmentos de YAML, además de la mezcla de tipos de datos de Python como diccionarios y matrices y fragmentos de YAML (que parecen estar algo procesados ​​como texto, un poco como usar un motor de plantilla HTML que genera etiquetas como cadenas) eventualmente resultó en demasiados errores y un archivo demasiado desordenado. Dhall también parece muy completo y utiliza un idioma nativo único que puede imprimirse en una variedad de formatos; Parece más un lenguaje de metaprogramación que un sistema de plantillas, sin embargo, dado que la sintaxis es funcional y está escrita de manera bastante estricta, rápidamente se volvió más complejo de lo que valía la pena para una plantilla simple para YAML no estructurado. Como lo que parece una mezcla de JSON y Haskell, requirió demasiado pensamiento para trabajar lo que necesitaba hacer en el lenguaje.

Curiosamente, algo que fue difícil tanto con Dhall como con ytt fue usar nombres de campo parametrizados, ambos habrían funcionado lo suficientemente bien de lo contrario, pero necesito que el nombre de mi instancia aparezca en los nombres de los servicios y los nombres de volumen, y en ambos lograr esto era algo feo; usar argumentos para los valores en un hash es fácil, pero usar esos argumentos en los nombres de las claves fue complicado o no pude encontrar cómo hacerlo de manera ordenada, además Dhall aplica la seguridad de tipos y esto simplemente va en contra de ese concepto. Con Jsonnet fue tan simple como poner la expresión entre corchetes.

CUE y Jsonnet están orientados a JSON, sin embargo, ejecutarlos a través de un convertidor no es nada difícil, y parece que, como Dhall, CUE tiene muchas características poderosas y nació de las deficiencias en Jsonnet, sin embargo, a mitad de camino en la documentación. , se hizo evidente que ya era exagerado; tal vez con mucho más tiempo para aprenderlo correctamente, sería la opción superior, pero parece que CUE está más orientado a la validación y los esquemas que un simple trabajo de plantilla, por lo que rápidamente pasé a Jsonnet y terminé el trabajo con bastante rapidez.

Finalmente, fue solo después de haber completado todo esto que me di cuenta de todo el tiempo que había estado comparando estas herramientas con la simplicidad de las etiquetas Liquid o plantillas HTML similares, que probablemente simplemente podría haber usado Liquid en primer lugar. Solo lo he usado en el contexto de un sitio de Jekyll, por lo que nunca se me ocurrió obtener un paquete independiente, sin embargo, con bucles y listas básicos, y la capacidad de evaluar expresiones directamente en texto en el lugar, esto probablemente habría ha sido mucho mejor también para el trabajo; Jsonify probablemente sea superior para JSON, pero Liquid podría funcionar en YAML puro y, por lo tanto, el archivo se vuelve más legible nuevamente.

+1 docker-compose fue una inspiración detrás de la solución a medida que implementé en el trabajo desde que este ticket se creó para admitir la migración de una gran cantidad de envs de prueba a k8s. Tuve mucho cuidado de evitar campanas y silbidos, pero rápidamente justifiqué una característica análoga. La discusión filosófica (composición versus herencia, etc.) me parece una distracción del sentido común (con el beneficio en retrospectiva, aún sin resolver casi 3 años después). Evidentemente, es requerido por personas que podrían continuar usando docker-compose.

+1: +1:

Usé mucho esta función antes para entornos dev / test / ci , donde podría extenderme desde un archivo de redacción en rutas de subdirectorio de ./config/{dev,test,ci}/compose.yaml . Tendría un .env que tuviera COMPOSE_ENV=dev , pero los desarrolladores podrían anular, y obviamente anularía en ci .

Me sorprende desaprobar la función y no reemplazarla con algo que pueda hacer algo similar. Tal vez solo nos permita usar jinja2 y hacer lo que queramos. Espero que Docker-Compose sea menos anti-DRY. : '(

Parece que extends es compatible con docker-compose desde v1.27 (https://github.com/docker/compose/pull/7588).

Un caso de uso en el que uso la función en gran medida es la versión de las imágenes de la ventana acoplable al código. Los archivos de composición de mi docker dev y prod se extienden desde docker-images.yml donde solo se enumera el servicio básico y una versión etiquetada de la imagen del servicio.

No encontré una solución fácil para esto en v3.

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