Moby: ¿Cómo combino varias imágenes en una a través de Dockerfile?

Creado en 29 dic. 2013  ·  97Comentarios  ·  Fuente: moby/moby

Tengo varios Dockerfiles para crear imágenes que, por ejemplo, configurar un cliente postgresql, configurar un entorno de aplicación Python genérico

Quiero hacer un Dockerfile para mi aplicación web de Python que combine ambas imágenes y luego ejecute algunos comandos más.

Si entendí los documentos correctamente, si uso FROM por segunda vez, ¿empiezo a crear una nueva imagen en lugar de agregarla a la actual?

arebuilder kinfeature

Comentario más útil

Puedo ver cómo hacer eso, es decir, genericA --> specificA pero hay alguna forma de hacer algo como:

genericA --
            \
             ---> specificAB
            /
genericB --

?

Todos 97 comentarios

los encadena :)

entonces, por ejemplo, si tiene un Dockerfile que configura su cliente de postgres genérico y su entorno de aplicación de Python genérico, etiqueta el resultado de esa compilación (por ejemplo, mygenericenv ), y luego sus Dockerfiles posteriores usan FROM mygenericenv .

por ejemplo

## Dockerfile.genericwebapp might have FROM ubuntu
cat Dockerfile.genericwebapp | docker build -t genericwebapp -
## Dockerfile.genericpython-web would have FROM genericwebapp
cat Dockerfile.genericpython-web | docker build -t genericpython-web -
## and then this specific app i'm testing might have a docker file that containers FROM genericpython-web
docker build -t thisapp .

Puedo ver cómo hacer eso, es decir, genericA --> specificA pero hay alguna forma de hacer algo como:

genericA --
            \
             ---> specificAB
            /
genericB --

?

No a través de ningún medio oficial, pero algunas personas han tenido suerte modificando manualmente la jerarquía de imágenes para lograrlo (pero si haces esto, lo haces bajo tu propio riesgo y te quedas con todas las piezas).

La razón por la que esto no será compatible oficialmente es porque imagina que quiero poner "ubuntu" e injertar "centos" en la parte superior. Habrá muchos conflictos realmente divertidos que causarán una pesadilla de soporte, así que si quieres hacer cosas así, estás solo.

Ok, veo por qué. Estaba buscando bloques de funcionalidad componibles, pero tal vez este no sea el caso de uso de Docker ... parece que debería usarlo para configurar los contenedores sin procesar y luego ejecutar algo como ansible o saltstack en la parte superior para configurar el software en ellos.

La idea detrás de los contenedores es que la unidad más pequeña de composición real es el contenedor. Es decir, un contenedor es lo más pequeño que puede producir de antemano, sin saber con qué más se combinará, y tiene fuertes garantías de cómo se comportará e interactuará con otros componentes.

Por lo tanto, cualquier unidad más pequeña que un contenedor, ya sea un script de ruby ​​o shell, un árbol de fuentes de C ++, un binario por sí solo, un conjunto de archivos de configuración, un paquete del sistema, etc., no se puede componer de manera segura, porque se comportará de forma muy diferente dependiendo de sus dependencias de compilación, dependencias de tiempo de ejecución y qué otros componentes forman parte de la composición.

Esa realidad puede quedar parcialmente enmascarada por la fuerza bruta. Tal fuerza bruta puede ser pragmática y "suficientemente buena" (Makefile gigante que detecta automáticamente todo para una compilación más portátil de su aplicación) o demasiado grandiosa ("modelemos de antemano cada posible permutación de cada dependencia e interferencia entre componentes, y expresemos ¡en una abstracción de alto nivel! ")

Cuando confía en Ansible, Chef o cualquier otra gestión de configuración para crear "componentes componibles", está confiando en una abstracción con fugas: estos componentes no son, de hecho, componibles. De un sistema a otro, producirán compilaciones que se comportan de manera diferente en un millón de formas. Toda la abstracción adicional al final te comprará muy poco.

Mi consejo es centrarse en 2 cosas: 1) el código fuente y 2) el contenedor ejecutable. Estos son los dos únicos puntos de composición fiables.

El domingo, 29 de diciembre de 2013 a la 1:46 p. M., Notificaciones [email protected]
escribió:

Ok, veo por qué. Estaba buscando bloques de funcionalidad componibles, pero tal vez este no sea el caso de uso de Docker ... parece que debería usarlo para configurar los contenedores sin procesar y luego ejecutar algo como ansible o saltstack en la parte superior para configurar el software en ellos.

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

Gracias por dar más perspectiva.

Entonces, ¿estás diciendo que para reutilizar partes de Dockerfiles, la única herramienta disponible es copiar y pegar? Viniendo más desde un punto de vista de 'desarrollo' que de 'operaciones', se siente un poco mal.

Tal vez sea un error tener el índice público de imágenes, hace que parezca que puedes compartir bloques de construcción reutilizables vagamente análogos a las recetas de Chef, pero mi experiencia hasta ahora es que no es útil porque:
a) para la mayoría de las imágenes no hay información sobre lo que hace y lo que hay dentro
b) los documentos alientan a enviar su trabajo al índice (para que luego pueda extraerlo) aunque lo que hizo probablemente no sea útil para otros, supongo que la mayor parte de lo que hay allí probablemente no valga la pena compartir

Siento que los documentos realmente no lo guían para usar Docker de una manera sensata en este momento

@anentropic La forma correcta de hacer esto con Dockerfiles es compilando varias imágenes con varios Dockerfiles.
Aquí hay un ejemplo: Dockerfile 1 crea una imagen genérica sobre una imagen base de Ubuntu, Dockerfile 2 usa la imagen resultante de Dockerfile 1 para construir una imagen para servidores de base de datos, Dockerfile 3 usa la imagen del servidor de base de datos y la configura para un rol especial .

docker build debería ser bastante fácil de ejecutar y no debería añadirse una complejidad innecesaria.

El índice público de imágenes es extremadamente útil. Las imágenes de Docker generalmente están destinadas a ejecutar un servicio o un grupo de servicios que no se pueden ejecutar en contenedores separados. Por lo general, puede extraer una imagen, ejecutarla y poner en funcionamiento un software útil sin mucho esfuerzo.

Entendido ... entonces, en el escenario que describí con el arte ascii arriba, la forma de Docker sería:

  • comience con Dockerfiles para imágenes independientes GenericA y GenericB
  • para hacer una imagen SpecificAB Copiaría y pegaría el contenido del GenericB Dockerfile en un nuevo Dockerfile que comienza con: FROM GenericA

El problema que veo es que si la 'receta' (para tomar prestado un término de Chef) por GenericB es bastante compleja y tiene muchos pasos, no hay forma de que pueda compartir esta información, excepto publicando el Dockerfile _to Github_ así que otros pueden _copiar y pegar_ las partes relevantes en su propio Dockerfile.

¿Ha intentado utilizar el índice público? Por ejemplo, hice una búsqueda de "postgres" ... ¿cómo puedo juzgar la utilidad de (o distinguir de alguna manera entre) imágenes como estas:

?

¿Qué valor brindan estos cuando la única forma de estar seguro de que tengo un servidor de Postgres configurado de la manera que quiero, en una imagen base en particular, sin nada dudoso escondido allí, será crearlo yo mismo desde cero?

Puedo ver el valor de algunas imágenes base 'oficialmente bendecidas' en un índice público. Puedo ver el valor de tener un índice privado de mis propias imágenes personalizadas listas para extraer.

Pero parece una pena que no haya forma (aparte de copiar y pegar) de compartir la serie de comandos en el Dockerfile como una receta ... como la sugerencia de un comando 'incluir' que fue rechazado aquí https: // github .com / dotcloud / docker / pull / 2108

@anentropic Puede usar una imagen confiable y también puede encontrar un Dockerfile postgres para construir la imagen usted mismo.

Las imágenes suelen ser más útiles cuando personaliza el Dockerfile para asegurarse de que se ajusten a sus necesidades exactas. Es por eso que ha descubierto que más usuarios han subido al registro una imagen para la misma pieza de software.

Es posible que las imágenes específicas existentes, como las imágenes de Postgres, no satisfagan sus necesidades particulares, pero también hay imágenes base que se pueden usar de inmediato para crear algo que sea útil para usted.

Las imágenes base como ubuntu , centos y algunas imágenes de stackbrew/* son imágenes que puede usar para construir lo que necesita.

Un ejemplo de una gran imagen lista para usar es stackbrew/registry . Esta imagen le permite jugar con un registro Docker privado tan pronto como docker pull stackbrew/registry y docker run -p stackbrew/registry terminen de ejecutarse.

El objetivo de Docker es ayudar con la implementación y la preparación del entorno donde se ejecuta su software. Esto significa que las compilaciones son lineales y se realizan solo durante la compilación inicial, pero ejecutará exactamente el mismo software cada vez.

Los sistemas de administración de la configuración pueden permitirle hacer algo más o emplear algunos otros trucos, pero no son tan "inmutables" y puede terminar teniendo dos hosts que tienen diferencias sutiles que no son detectadas por el software de administración de la configuración.

Odio necro un hilo antiguo, pero quería ofrecer algo que en mi humilde opinión ayude a resolver el problema de los carteles originales y pueda ayudar a otros que buscan una solución similar a este problema aquí.

Supongamos por simplicidad que todos usan la misma imagen base R . Imagina que tengo el servicio A y el servicio B . Los quiero en imágenes de Docker separadas y ambas en la misma imagen de Docker.

Escriba una secuencia de comandos para instalar el servicio A y escriba una secuencia de comandos separada para instalar el servicio B . Luego tenga un repositorio de git con el script para A y otro para el script B . Cree repositorios de git para las tres imágenes de Docker que se compilarán. Cada uno contiene submódulos de git con los scripts de instalación que se utilizarán. Cada Dockerfile simplemente ADD un script de instalación y luego RUN el script de instalación y hacer esto para uno o ambos scripts. Si desea eliminar el (los) script (s) de la imagen, agréguelo después de ejecutarlo.

De esta manera, hay una copia de cada secuencia de comandos de instalación y cualquier imagen de la ventana acoplable que desee usar. Esto evita la copia innecesaria de código y mantiene la carga de mantenimiento mínima. La única duplicación de esfuerzos es subir la confirmación utilizada por los submódulos, que es significativamente mejor que la alternativa y probablemente podría automatizarse.

Creo que no entiendo bien cómo funciona esto, así que respondo para obtener una aclaración. Quiero usar Ubuntu 11 con las imágenes oficiales de la ventana acoplable de selenio. Usan Ubuntu 15.

https://github.com/SeleniumHQ/docker-selenium/blob/master/Base/Dockerfile

¿Cuál es la forma correcta de hacer esto? ¿Clonar ese repositorio y editar todos los archivos para decir Ubuntu 11 y no 15? Esto no puede ser correcto, ¿verdad? Esto significaría que todas las personas que no estén de acuerdo con cualquier aspecto de las imágenes oficiales no pueden hacer uso de ellas sin duplicar el código. Creo que me equivoqué, ¿alguien puede explicarlo? ¿Cuál es la forma correcta de utilizar la imagen oficial de selenium con Ubuntu 11?

@rjurney sí, así es como funcionaría; en su ejemplo, todo el Dockerfile se desarrolla con ubuntu: 15.04 en mente; ¿Están esos paquetes disponibles en ubuntu: 11? ¿Funcionan? ¿El selenio corre sobre ellos? Lo más probable es que sea necesario realizar modificaciones en el Dockerfile para que funcione en otra versión de Ubuntu.

"intercambiar" la imagen base de una imagen existente tampoco funcionaría, porque Docker solo almacena las _diferencias_ entre la imagen base y la imagen. Por lo tanto, el uso de una imagen base diferente conduce a resultados impredecibles (por ejemplo, "eliminar archivo X", donde "archivo X" existe en la imagen base original, pero no en la imagen base que seleccionó). Además, los paquetes / binarios en imágenes que se construyen "encima" de una imagen base, son paquetes que se construyen para _ esa_ versión, esos binarios pueden no ser compatibles con una imagen base diferente.

Esto significaría que todas las personas que no estén de acuerdo con cualquier aspecto de las imágenes oficiales no pueden hacer uso de ellas sin duplicar el código para ellas.

Si. Las imágenes oficiales están respaldadas por los mantenedores de esas imágenes (que en este caso, son los mantenedores de Selenium). Si cree que se necesitan cambios en esas imágenes, la mejor manera es abrir una solicitud de función en su repositorio. Si no se acepta esa solicitud de función, probablemente debería crear su propia versión.

(Tenga en cuenta también que no hay una imagen oficial ubuntu:11 )

En el resto del mundo del software, la herencia única no se considera
adecuado para expresar razonablemente la semántica necesaria. Conduce a mucho código
duplicación, que se consideraría un error. ¿Por qué se ve esto como
aceptable para docker? Incluso si está creando un servicio a la vez,
La composición es necesaria a nivel del sistema operativo. No me refiero a vencer a un
caballo muerto, pero este límite parece un poco extremo. Podría ser mejor
expresada como una mejor práctica? Como resultado de la rigurosidad de este
decisión, alguien construirá una herramienta que haga composición o múltiples
herencia y los expresa a través de la herencia única y la duplicación.
Tener esto fuera de la ventana acoplable propiamente dicha no servirá a la comunidad de la ventana acoplable.

El miércoles 9 de diciembre de 2015, Sebastiaan van Stijn <
[email protected]> escribió:

@rjurney https://github.com/rjurney sí, así es como funcionaría; en
su ejemplo, todo el Dockerfile se desarrolla con ubuntu: 15.04 en mente;
¿Están esos paquetes disponibles en ubuntu: 11? ¿Funcionan? ¿El selenio corre
¿en ellos? Lo más probable es que sea necesario realizar modificaciones en el Dockerfile
para que funcione en otra versión de Ubuntu.

"intercambiar" la imagen base de una imagen existente tampoco funcionaría, porque
Docker solo almacena las _diferencias_ entre la imagen base y la
imagen. Por lo tanto, el uso de una imagen base diferente conduce a impredecibles
resultados (por ejemplo, "eliminar archivo X", donde "archivo X" existe en la base original
imagen, pero no en la imagen base que seleccionó). Además, los paquetes / binarios
en las imágenes que se crean "encima" de las imágenes base, son paquetes que se crean
para _ esa_ versión, esos binarios pueden no ser compatibles con una versión diferente
imagen base.

Esto significaría que todos los que estén en desacuerdo con cualquier aspecto de
las imágenes oficiales no pueden hacer uso de ellas sin duplicar el código para ellas

Si. Las imágenes oficiales están respaldadas por los mantenedores de esas imágenes.
(que en este caso, son los mantenedores de Selenium). Si crees que cambia
son necesarios para esas imágenes, la mejor manera es abrir una solicitud de función en
su repositorio. Si esa solicitud de función no es aceptada, debe
probablemente construya su propia versión.

(También tenga en cuenta que no hay una imagen oficial de ubuntu: 11)

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

La herencia múltiple de extremos y las incompatibilidades.

12749 fue el último intento de agregar dicha funcionalidad; finalmente se rechazó porque hay otro trabajo por hacer primero.

Se está trabajando mucho en el constructor, incluida la habilitación de compilaciones impulsadas por el cliente que pueden abrirlo bastante.

Los archivos Dockerfiles de herencia única funcionan para la (gran) mayoría de los casos de uso, por lo que no hay prisa por mejorar esto. Debe hacerse de manera correcta y deliberada.
Y según sus comentarios anteriores, diría que en realidad no necesita herencia múltiple, solo una forma de especificar una imagen base contra la que se ejecuta el Dockerfile sin duplicar el código existente.

Eso satisfaría mis necesidades, sí. Pudiendo modificar alguna propiedad del
cadena de archivos docker.

Ok, me alegra saber que estás al tanto de esto. Gracias por su paciencia :)

El miércoles 9 de diciembre de 2015 a las 9:59 a. M., Brian Goff [email protected] escribió:

@rjurney https://github.com/rjurney la herencia múltiple también es
extremadamente complejo y no solo algo que simplemente agrega sin pensar
por consecuencias, casos de esquina e incompatibilidades.

12749 https://github.com/docker/docker/pull/12749 fue el último

intento de agregar dicha funcionalidad, que finalmente se rechazó porque hay
otro trabajo debe hacerse primero.
Se está haciendo mucho trabajo en el constructor, incluida la habilitación
compilaciones impulsadas por el cliente que pueden abrir esto bastante.

Los archivos Dockerfiles de herencia única funcionan para la (gran) mayoría de los casos de uso,
como tal, no hay prisa por mejorar esto. Debe hacerse correctamente y
deliberadamente.
Y según sus comentarios anteriores, diría que en realidad no necesita múltiples
herencia, solo una forma de especificar una imagen base en la que se ejecuta el Dockerfile
contra sin duplicar el código existente.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney ¿

En mi opinión, lo que necesitamos para la ventana acoplable no es el concepto de herencia múltiple, sino el concepto de inclusión o dependencias externas. Por ejemplo, puede montar contenedores en tiempo de ejecución. Lo que realmente se necesita es un camino al equivalente con imágenes. Entonces, por ejemplo, podría tener una imagen que se definió para estar basada en Fedora 22 y montar una imagen de Oracle para agregar la funcionalidad de la base de datos.

Esto se puede hacer con bastante éxito cuando se ejecutan contenedores, pero simplemente no existe una sintaxis para especificarlo con imágenes. Entonces, hasta el tiempo de ejecución, no hay forma de que Docker pueda conocer estas dependencias o administrarlas por usted.

Tenga en cuenta que mencioné herencia y composición múltiples.
La composición es la forma preferida de hacer esto, definitivamente.

Estoy de acuerdo con todo lo demás que dijiste, así que +1.

El miércoles 9 de diciembre de 2015, Bill C Riemers [email protected]
escribió:

@rjurney https://github.com/rjurney ¿De dónde obtiene su información?
Que yo sepa, Java nunca ha tenido herencia múltiple, y nunca la tendrá.
Estoy seguro de que lo mismo ocurre con muchos idiomas. Muchos consideran múltiples
herencia extremadamente dañina, ya que puede resultar en casi imposible
código predecible. Lo mismo sería cierto para un contenedor docker.

Como yo lo veo, lo que necesitamos para Docker no es el concepto de múltiples
herencia, sino el concepto de inclusión o dependencias externas. p.ej
Puede montar contenedores en tiempo de ejecución. Lo que realmente se necesita es una forma de
el equivalente con imágenes. Entonces, por ejemplo, podría tener una imagen que
se definió para estar basado en Fedora 22, y montar una imagen de Oracle para agregar
funcionalidad de la base de datos.

Esto se puede hacer con bastante éxito cuando se ejecutan contenedores, pero hay
simplemente no hay sintaxis para especificarlo con imágenes. Así que hasta el tiempo de ejecución no hay
la forma en que Docker puede conocer estas dependencias o, de todos modos, administrarlas para
Uds.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

Me voy a callar después de esto, pero puse esta perorata en la solicitud de extracción antes mencionada en lugar de este ticket, por error. Así que lo estoy poniendo aquí.

Alguien va a construir esto. No aceptar un tirón que agregue INCLUDE retrasará y externalizará esta característica. Esta debería ser la base de la decisión aquí: ¿debería ser dentro o fuera de la ventana acoplable?

Me viene a la mente un ejemplo. En Apache Pig, el equipo tomó la decisión de no incluir bucles, a pesar de muchas solicitudes para ellos, porque se decidió que Pig debería ser excelente para los flujos de datos DAG y eso es todo. En su lugar, se creó una integración para realizar secuencias de comandos de cerdo, de modo que pudiera recorrer las secuencias de comandos desde cualquier lenguaje JVM. Tenga en cuenta que esta fue una decisión consciente y que se buscaron alternativas. Este es el proceso modelo en mi opinión.

Otro ejemplo de Pig me viene a la mente ... Pig Macros. No existían y eran 'un cerdo' hasta que alguien (ok, yo) comenzó un hilo sobre lo increíblemente feo que era su gran proyecto de cerdo y que no había forma de solucionar este problema sin generar Pig desde una herramienta externa, que era indeseable. Mucha gente intervino y el equipo de Pig agregó macros. Las macros hacen posible un cerdo limpio y la comunidad se beneficia.

Le sugiero que aborde la decisión de frente y tenga una discusión al respecto, lo que aún no ha ocurrido aquí, y para la búsqueda probablemente pertenezca aquí. Esto existirá. La duplicación de scripts en idiomas específicos de un dominio es terrible. La gente lo demandará. ¿Esta función estará dentro de Docker o fuera de Docker? ¿Cómo facilitará este comportamiento fuera de Docker?

Lo siento, probablemente me esté perdiendo mucho contexto en la lista de correo, pero como nuevo usuario de Docker ... me siento muy reacio a hacer mucho con Docker sin la capacidad de componer dockerfiles a partir de recetas existentes. Fui por este camino con Pig y casi me mata. Creo que mucha gente se sentirá así.

En caso de que a alguien le importe ...

La presentación a medio adoptar sobre bucles y macros en Pig: http://wiki.apache.org/pig/TuringCompletePig
Macro de cerdo JIRA: https://issues.apache.org/jira/browse/PIG-1793
Interfaz API para Pig JIRA: https://issues.apache.org/jira/browse/PIG-1333
Uno que fue completamente rechazado para respetar Apache Hive ... agregue SQL a Pig: https://issues.apache.org/jira/browse/PIG-824

Finalmente, tuve una idea que podría facilitar este cambio ... ¿y si los archivos INCLUDE no se pueden heredar? es decir, evitaría objeciones manteniendo las cosas súper simples. Trate el resto más tarde a medida que se aprenda más. Podría haber un Dockerfile simple, por ejemplo, que instale los requisitos previos y los binarios, y configure demonios para MySQL en Ubuntu. Si es necesario, esto podría ser versionado por la versión de Ubuntu y MySQL. Personalmente, voy a piratear una utilidad para hacer estos INCLUDES simples y usarla para organizar mis archivos docker de esta manera. No puedo esperar para ordenar y reutilizar mi código.

+1 para la idea INCLUIR. Aunque creo que prohibir la herencia solo cambiará el problema, ya que ahora podría modificar la imagen principal de la que está heredando, pero no las otras imágenes que incluye. Básicamente, lo que tendría sentido sería si pudieras especificar que una imagen sea "incluible" en el sentido de que no ofrece ningún elemento del sistema operativo que pueda romper el elemento de la imagen base existente. Esta bandera tendría que ser establecida por el proceso de compilación de la ventana acoplable y evitaría que se incluyan imágenes marcadas no adecuadamente. Y quiero decir, seamos sinceros. Si está jugando con Dockerfiles, probablemente no sea una persona que esté viendo su máquina el primer día, así que creo que si bien tiene sentido evitar que el usuario final de la ventana acoplable haga cosas estúpidas, debería haber un poco más libertad para los chicos que realmente crean esas imágenes. Y lo digo en serio, ser capaz de seleccionar una imagen base e incluir todo lo que quiero en ella para aprovisionar mi aplicación sería bastante increíble.

+1 para INCLUIR. Simplemente necesito una imagen nginx y ssh combinada en una. ¿Por qué esto tiene que ser tan difícil?

La idea de que esto no es necesario es francamente confusa hasta el punto de ser
falso. La mayoría de los usuarios usarán esto, si se crea. "Agregar ssh a
ubuntu "y" agregar nginx a ubuntu "son tareas bastante comunes que todos
no es necesario repetir. Lo que Docker HQ realmente parece estar diciendo al respecto es:
"Obviamente es necesario, pero creemos que se pondrá demasiado feo. Así que fingimos". Eso
Sería mejor si pudiera ser honesto y abierto sobre esto.
Lo siento si estoy de mal humor.

El sábado 23 de enero de 2016 a las 6:22 p.m., Vazy [email protected] escribió:

+1 para INCLUIR. Simplemente necesito una imagen nginx y ssh combinada en una. Por qué
¿Esto tiene que ser tan difícil?

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney , esperemos el spin-out de la compilación; porque de esta manera, habrá más de una forma de construir imágenes (y así podría aparecer un constructor personalizado que lo haga). Una de las razones por las que los mantenedores de Docker (trabajando o no para Docker) son juguetones al respecto es porque agregaría complejidad donde queremos agregar flexibilidad y simplicidad. Al extraer el constructor, tendremos una mejor separación de preocupaciones (entre construir imágenes y ejecutarlas) y muchos casos de uso se implementarán más libremente en los constructores personalizados.

De nuevo, ¿estás sacando esto del proyecto? Sonidos personalizados ... no
la forma predeterminada, incluida. Cuando de hecho, las inclusiones son una simple necesidad que
casi todo el mundo tiene. Repetirse es complejidad. La herencia solo es
complejidad. Incluye coincide con una necesidad que todos tienen de la manera más sencilla.
posible.

El domingo 24 de enero de 2016, Vincent Demeester [email protected]
escribió:

@rjurney https://github.com/rjurney esperemos el spin-out de la compilación;
porque de esta manera, habrá más de una forma de construir imágenes (y por lo tanto
podría aparecer un constructor personalizado que haga eso). Una de las razones por las que Docker
los mantenedores (que trabajan o no para Docker) son juguetones al respecto, es
porque agregaría complejidad donde queremos agregar flexibilidad y
sencillez. Al extraer el constructor, tendremos una mejor separación de
preocupación (entre crear imágenes y ejecutarlas) y muchos casos de uso
se implementará más libremente en los constructores personalizados.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

+1, combinar imágenes sería extremadamente útil. Imagine un caso de uso de C ++ (Dios no lo quiera). Construyo una imagen con boost, otra con, digamos Qt, todas con el mismo compilador, etc. Ahora digamos que quiero construir una aplicación con boost y Qt, solo necesito combinar los dos y listo: un entorno de desarrollo listo. Esto sería increíblemente útil.

Personalmente, creo que este es un tema demasiado importante para no abordarlo. Dicho esto, necesitamos comprender bien cuáles son los problemas y el alcance, independientemente de dónde se implemente.

Entonces, veo estos problemas presentados por la fusión.

  1. Manejo de conflictos de fusión.
  2. Resolución de diferentes bases (Ubuntu y CentOS).

Con el primero, creo que la respuesta simple es no. Para mí, suena demasiado complicado y potencialmente problemático y requeriría un conjunto de herramientas para resolverlo y aún podría ser demasiado mágico. Entonces, si esto se agregara, los conflictos de fusión deberían fallar. Supongo que podría revisarse más tarde, pero parece más problemático de lo que vale la pena.

En cuanto al segundo caso, parece que podría agregar una restricción de que comparten algunas capas base. Ahora la pregunta es cuántos son suficientes. Creo que la respuesta correcta al comenzar sería que las dos imágenes que se fusionan deben tener la misma imagen FROM . Puede que sea necesario que haya más restricciones aquí, pero no me queda claro que esos casos no se incluyan en el problema 1, que se ha resuelto simplemente denegándolo.

¿Hay otros problemas que me faltan aquí?

Creo que no debería haber ningún intento de fusionar ... No puedo ver que eso suceda

Un enfoque más realista podría ser un tipo de solución basada en plantillas, es decir, permitir INCLUDE un Dockerfile _fragment_ (que no tiene una cláusula FROM , solo una lista de comandos) en un Dockerfile real ... los fragmentos se pueden compartir, reutilizar e incluir en cualquier archivo Dockerfile de imagen base compatible

Soy completamente nuevo en Docker y estoy aprendiendo con humildad. Pero pensé que el punto principal de Docker era construir aplicaciones _reutilizables_ muy pequeñas para luego combinarlas de cualquier forma en grandes aplicaciones finales como en una aplicación web. Si es así, en mi humilde opinión, una declaración como INCLUDE es obligatoria.

@jmcejuela en muchos casos "reutilizar" es crear imágenes dedicadas a un servicio específico y combinar esas imágenes / contenedores para formar su aplicación. Los componentes individuales de su aplicación son reutilizables (posiblemente, solo difiere la configuración del contenedor), pero la forma en que los combina forma la aplicación real.

@thaJeztah Lo entiendo, gracias.

Pero haciéndolo concreto como las personas publicadas antes, digamos que construyo una aplicación web que ejecuta una aplicación scala (imagen A ), luego hago el servidor web con nginx (imagen B ), luego tengo ssh (imagen C ), y necesita una aplicación de Python adicional (imagen D ). Digamos que he creado 4 Dockerfile para cada uno. ¿Cómo los combino con Docker para crear mi aplicación web final (imagen E ?)

Solo necesito una forma sencilla de hacer esto. No me importan las disputas filosóficas sobre la herencia múltiple, incluir o no, componer o no, etc. Aunque ciertamente no me gustaría copiar y pegar como se propuso antes.

Muchísimas gracias por su tiempo. Todavía estoy aprendiendo Docker.

@jmcejuela , no combinarías las _images_, las ejecutarías como contenedores separados y harías que cooperaran para formar la aplicación. Puede hacerlo utilizando Docker Compose, que le permite definir su "pila". Por ejemplo, consulte https://github.com/docker/example-voting-app/blob/master/docker-compose.yml (y el archivo README; https://github.com/docker/example-voting-app/ blob / master / README.md)

Para la parte "ssh", realmente depende para qué lo quieras usar; en general, los contenedores se consideran "inmutables", por lo que no se introducirá en un contenedor y no se modificará, sino que se activará un nuevo contenedor para reemplazar el anterior; los datos que deben persistir más allá del ciclo de vida de un contenedor se almacenan en un volumen, de modo que el nuevo contenedor pueda usar esos archivos.

@jmcejuela El constructor de Docker acepta contenido de Dockerfile en STDIN, por lo que uno podría generar uno "relativamente" fácilmente. Si se debe pasar un contexto, entonces todo debe ser alquilado y alimentado a docker build . En mi experiencia, esta es la forma más sencilla posible de obtener una composición.

Estoy desarrollando (y jugando con) un enfoque que se basa en el concepto anterior. Una aplicación nodejs prepara un archivo TAR en la memoria (con Dockerfile y archivos agregados) y lo vuelca a STDOUT. El STDOUT se canaliza a docker build . Las partes componibles se versionan, prueban y lanzan como módulos NPM. Pongo un ejemplo muy corto, que demuestra una imagen de prueba por crond - http://pastebin.com/UqJYvxUR

Gracias @thaJeztah Al final, solo necesito un solo archivo que mis co-desarrolladores puedan ejecutar para tener toda la pila de desarrollo, y luego poder ejecutarlo en prod también si es necesario. Examinaré más profundamente la composición de Docker.

Además, INCLUDE se propuso hace mucho tiempo (https://github.com/docker/docker/issues/735).

@jmcejuela El hecho es que la mayoría de los usuarios de Docker instalan y usan ssh para configurar contenedores y solucionar problemas en un contenedor en ejecución. Así es como se usa realmente la ventana acoplable.

Solo si lo estás haciendo mal, el comando docker exec ha existido durante bastante tiempo y nunca he necesitado ssh desde ...

@anentropic Eso solo es válido si está implementando servicios simples sin dependencias. Si tiene una cadena compleja de dependencias para cualquier servicio, cualquier cosa que involucre aprendizaje automático, por ejemplo, estará duplicando código para implementar servicios. Y no hay una buena razón por la que debas hacerlo. El hecho de que Docker sea un lenguaje de dominio específico no significa que la mayor parte del conocimiento sobre los lenguajes de programación se descarte y no se aplique ninguna de las lecciones anteriores. La cordura todavía debe importar. Copiar y pegar recetas es una locura.

También es válido solo si se suscribe a la visión del mundo de 'servicio único', que no es para todos los usuarios de la ventana acoplable.

@anentropic Según la hoja de ruta de Docker, el aprovisionamiento de contenedores en ejecución a través de docker exec puede ser igualmente incorrecto.

PD: El motor rkt ha llegado a la v1.0.

@rjurney,: 100:

La herencia múltiple, ya sea amada u odiada, es una característica compleja y sin duda tendrá resistencia. Incluir convierte Dockerfiles de una receta de compilación a un lenguaje con problemas de ruta que son difíciles de resolver.

¿Qué pasa si miramos el problema de otra manera? ¿Qué pasaría si pudiéramos " ADD / COPY " seleccionar archivos de otra imagen de la ventana acoplable en una que se está construyendo? De esta manera, uno puede beneficiarse de la reutilización de la funcionalidad y evitar la duplicación de código. Como no estamos usando FROM varias veces en una imagen, sino simplemente copiando binarios de manera explícita, esto debería comportarse de una manera bien definida y cuando no lo hace, es un error. Dado que esto funciona con imágenes de la ventana acoplable y es capaz de aprovechar los registros como solución en lugar de una nueva ruta de búsqueda, espero que esta sea una propuesta razonable. Una ventaja adicional es que tampoco tenemos que volver a ejecutar el mismo código varias veces. Además, con suerte, se podría evitar un cambio masivo en el constructor. ¿Pensamientos?

Tal vez esto se proponga en otro lugar, en cuyo caso un enlace sería bueno.

Hola,
Cualquiera que sea la solución que se seleccione, preparar una imagen a partir de múltiples fuentes independientes es algo que me sorprendió mucho que es imposible.
Me hubiera gustado omitir la preparación de la imagen, ya que en tiempo de ejecución podemos realizar este proceso, de modo que en el tiempo de ejecución se implementará un conjunto de imágenes, sin necesidad de rehacer la imagen cada vez que se modifica una dependencia.
Busqué alternativas, todavía no he encontrado ninguna válida, esta es una brecha de uso importante.
Parece bastante fácil de realizar con ACI.
¡Gracias!

: +1: me encantaría una solución a esto y me alegro de que al menos se esté hablando de ello. Incluso si requiere que las imágenes base sean las mismas.

Resulta que la copia de otras imágenes se propone en otra parte. Este es el problema (https://github.com/docker/docker/issues/18596).

gracias @jakirkham ..

+1 para la funcionalidad de herencia múltiple de Docker

Creo que el problema con el que se está encontrando es que la incapacidad para redactar recetas no tiene sentido. Docker compose es ideal para usar varios contenedores en una aplicación. El enjambre de Docker es ideal para hacer lo mismo con varios nodos. Pero no hay forma de incluir el trabajo de otros a nivel de código fuente, en muchos casos. Debe heredarlo una vez o volver a crearlo, lo cual es limitante.

El viernes 18 de marzo de 2016 a las 9:01 a. M., Alvin Chevolleaux < [email protected]

escribió:

La respuesta de @thaJeztah https://github.com/thaJeztah es muy
esclarecedor. Soy nuevo en Docker y no entiendo por qué no puede combinar
múltiples _imágenes_ juntas, pero Docker Compose parece ser la solución para
combinando múltiples _contenedores_ en una aplicación que estaba buscando
por.

Creo que el problema para mí es que pensé que entendía Docker al principio
pero ahora estoy descubriendo que no. Voy a volver y hacer un poco más
¡leyendo!

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/docker/issues/3378#issuecomment -198426036

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney Sí, después de mirar en Docker Compose un poco más, estás en lo cierto, esa es exactamente mi confusión. Por ejemplo, hay una imagen PHP y una imagen Centos, pero no hay herencia entre diferentes imágenes, por lo que es una especie de todo o nada. En la imagen oficial de PHP está usando debian:jessie pero quiero que mi configuración esté basada en Centos, así que parece que si quiero usar una imagen en particular debo aceptar el resto de la configuración o copiar y pegar el Dockerfile de origen y rodar mi propia imagen desde cero, no parece haber un término medio donde pueda mezclar y combinar imágenes.

EDITAR:
Solo para aclarar, entiendo por qué no se pueden mezclar imágenes basadas en Ubuntu y Centos juntas, pero no veo por qué no se puede tener algún tipo de estructura jerárquica. Luego, en lugar de descargar una imagen completa, simplemente descargaría los cambios de una imagen a otra.

INCLUDE sería increíblemente útil para mí. Sin él, me queda copiar y pegar.

@RomanSaveljev No lo entiendo:

Según la hoja de ruta de Docker, el aprovisionamiento de contenedores en ejecución a través de docker exec puede ser igualmente incorrecto.

No dice que docker exec quedará obsoleto. docker exec siempre ha sido una herramienta de depuración, al igual que SSH en un contenedor Docker.

Me siento tonto por participar en esto, pero qué diablos ... Sugeriré esto nuevamente:

¿Por qué no simplificamos el problema y comenzamos implementando INCLUDE para que no permita la herencia? En otras palabras, solo puede incluir archivos que no tengan FROM.

Eso manejaría muchos casos de uso, y el ímpetu estaría en los archivos que la gente INCLUYE para trabajar en cualquier sistema operativo razonable. uname existe por una razón. Este sería un primer paso, y los comentarios sobre esta implementación ayudarían a definir algo más.

Parece una decisión fácil de tomar. No sería mucho trabajo. No sería complejo. ¿Correcto?

@rjurney eso es básicamente lo que hace https://github.com/docker/docker/pull/12749

@rjurney : No te sientas tonto. Si bien INCLUDE no cubre completamente la solicitud inicial, es un paso en la dirección correcta. Hay varios problemas encapsulados.

  1. ¿Cómo combinar varias piezas de trabajo independiente?
  2. ¿Cómo almacenar estas compilaciones de manera eficiente?
  3. ¿Cómo combinar varias piezas de trabajo a nivel binario, no a nivel de construcción?

Probablemente hay más elementos que podrían agregarse a esta lista. La solución INCLUDE maneja el primer punto de viñeta. Una vez que está en su lugar, se establece un marco estándar donde la eficiencia del almacenamiento binario podría mejorarse de forma transparente para el usuario final. Una vez que esté en su lugar, entonces tiene sentido hablar de herramientas que hacen las mismas manipulaciones en los archivos de imagen directamente. Sin embargo, este último paso es, por supuesto, muy cuestionable. Tan pronto como lo haga directamente en los archivos de imagen, existe un gran potencial para terminar con una imagen rota. Sin embargo, si se asume que solo los usuarios avanzados (aquellos que saben exactamente lo que están haciendo) harán la tercera opción, eso para mí no parece una adición irrazonable ... eventualmente.

Para aquellos que quieran algo realmente componible de esta manera, podrían mirar Nix (NixOS, un sistema de administración de paquetes y distribución de Linux). Simplemente requiere que vuelva a empaquetar todo su software, generalmente compilado a partir de la fuente, y abandone todo lo que pensaba que sabía sobre Linux;). Es un buen sistema, pero requiere mucho trabajo dado que no mucha gente lo usa, pero espero sinceramente que se ponga al día.

Como han dicho otros, la capacidad de compilación de Docker se trata más de componer a nivel de servicio.

: +1: defo vale la pena pensar en un modelo componible; sería genial si pudieras importar comportamientos en un dockerfile. por ejemplo, ahora tengo un caso de uso en el que quiero incluir apache thrift en una serie de contenedores de compilación muy diferentes basados ​​en Alpine linux: algunos compilarán servicios Java, otros PHP y otros Node.

Sería bueno poder incluir la instalación de ahorro en lugar de copiar y pegar; sin embargo, creo que puedo extraer fácilmente a un script de shell y AGREGARLO y EJECUTARLO.

Entonces, ¿cómo uso las imágenes ruby-2.3 y java-8? Usan la misma imagen debian jessie como base (leí los dockerfiles). Solo quiero ejecutar los comandos presentes en ambos. Tal como está, tuve que copiar / pegar el Dockerfile de Java en Ruby Dockerfile. La aplicación necesita ambos, no hay absolutamente ninguna forma de evitarlo.

Aproveché la oportunidad para eliminar algunos comandos de Dockerfile mientras los pegaba; no eran dañinos, sino simplemente superfluos, ya que el Dockerfile "base" (en el que estaba pegando comandos) ya realizaba esos pasos. Por lo tanto, puedo ver el argumento de que realmente no quería una imagen "ruby" y "java", en realidad estaba construyendo una tercera imagen "ruby + java todo en uno".

Sin embargo, en este caso particular, los comandos en esas dos imágenes parecen ser totalmente compatibles; si simplemente los concatenara, deberían funcionar. Sería útil poder especificar tales circunstancias. No soy un gran admirador del enfoque de copiar / pegar; en mi caso, los Dockerfiles de Java y Ruby eran lo suficientemente simples, pero algunos Dockerfiles son mucho más complejos.

Sin embargo, para todos los que, como yo, quieren esta función, puedo ver muchas situaciones en las que esto sería problemático. Por lo tanto, no se trata solo de proporcionar la capacidad de ejecutar "nginx" y luego "ssh" en la misma imagen de la ventana acoplable; la misma funcionalidad también le permitiría ejecutar "debian" y "centos", que definitivamente no producirán un imagen viable. Si alguna vez se introduce, parece que tendría que ser una opción experimental, desactivada de forma predeterminada, que tiene un montón de advertencias adjuntas.

Entonces, sea cual sea la interfaz de esta función, debería dejar muy claro que la responsabilidad de obtener los comportamientos reutilizables (conjuntos de comandos) correctos recae en el desarrollador de Dockerfile.

EDITAR: Ah, me perdí la discusión INCLUDE.

¿Por qué no simplificamos el problema y comenzamos implementando INCLUDE para que no permita la herencia? En otras palabras, solo puede incluir archivos que no tengan FROM.

Eso manejaría muchos casos de uso, y el ímpetu estaría en los archivos que la gente INCLUYE para trabajar en cualquier sistema operativo razonable. uname existe por una razón. Este sería un primer paso, y los comentarios sobre esta implementación ayudarían a definir algo más.

Parece una decisión fácil de tomar. No sería mucho trabajo. No sería complejo. ¿Correcto?

: +1:

@rjurney eso es básicamente lo que hace # 12749

: +1: perfecto, deseando ver lo que podrá hacer en su forma final.

Muy interesado en este concepto también. Un mecanismo "INCLUYE" es una solución muy burda, pero honestamente representaría un gran paso adelante en el mantenimiento de un conjunto de archivos docker.

Personalmente, no querría que _fallase_ cuando encuentre un FROM , quisiera que _ ignore_ el FROM y simplemente aplique el resto de los comandos en secuencia.

Que esto no haya sucedido todavía sin el soporte de FROM es un código abierto
parodia.

El jueves 19 de enero de 2017 a las 10:19 a.m., Ken Williams [email protected]
escribió:

Muy interesado en este concepto también. Un mecanismo "INCLUYE" es muy
solución cruda, pero honestamente representaría un gran paso adelante en
mantenibilidad de un conjunto de archivos Docker.

Personalmente, no querría que fallara cuando encuentre un FROM, lo haría
quiero que ignore el FROM y simplemente aplique el resto de los comandos en
secuencia.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/docker/docker/issues/3378#issuecomment-273854850 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AACkpS8-EQ7r0BHid75rxeBDhOUDFRXlks5rT6kXgaJpZM4BWkJ9
.

-
Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

Aquí está la cosa, no necesariamente necesito fusionar. Creo que muchos de los problemas podrían resolverse con una nueva base. Mi caso de uso normal es

A (ubuntu) -> B (por ejemplo, nginx)
A (ubuntu) -> C (por ejemplo, nodo)

Y quiero una imagen B y C combinada. Por lo general, no tienen nada que ver entre sí, por lo que sería suficiente con rebasar todas las diferencias entre A y C en B. es decir.

A -> B -> C '

Parece un problema más sencillo de resolver.

@cloutiertyler Normalmente, las aplicaciones Node.js no necesitan esta característica para funcionar con Nginx (en mi opinión). El método Docker sería dos contenedores, uno para Nginx y el otro para Node. Configuramos el contenedor Node para exponer su puerto solo al contenedor Nginx, y dejamos que el contenedor Nginx escuche el puerto público (como 80). ¿Alguna razón por la que Nginx necesita estar en el mismo contenedor que Node?

Un archivo de Docker Compose de muestra puede ser

version: "2.1"

services:
  app: # Node.js application image
    build: .
  nginx: # Nginx container who can make request to app container
    image: nginx:1.10-alpine
    depends_on:
      - app
    ports:
      - "${PORT:-8080}:80" # public port, you may want PORT=80

@franklinyu Agradezco la respuesta. De hecho, solo utilicé dos servicios aleatorios como ejemplo. Mi caso de uso habitual sería comenzar con un servicio genérico (por ejemplo, un nodo basado en ubuntu) y una imagen personalizada propia (también basada en ubuntu) y querer combinarlos.

por cierto, no se trata exactamente de un cambio de base, pero abre muchos casos de uso para Dockerfiles.
Dockerfile ahora admite compilaciones de varias etapas. Ejemplo:

FROM golang AS myapp
COPY . /myapp
RUN cd /myapp && go build

FROM scratch
COPY --from=myapp /myapp /usr/bin/myapp

Puedes tener tantas etapas como quieras.
El parámetro --from básicamente cambia el contexto al nombre de destino de compilación especificado.
Cuando docker build -t myapp . , la imagen resultante llamada myapp:latest será de la última etapa.
También puede crear etapas específicas con docker build --target=myapp , por ejemplo.

Hay algunas otras mejoras muy agradables de Dockerfile en 17.05 (actualmente disponible como RC1), ¡pruébalo!

¡Eso sí que es interesante! No sabía que podías hacer eso. Tendré que intentarlo para ver si resuelve mis casos de uso comunes.

Si bien esta es una gran característica, después de haberla probado, realmente no resuelve mi problema más común. Me lo encontré de nuevo hoy.

Me gustaría una imagen de Jenkins que tenga Docker instalado para poder compilar desde el contenedor. El hecho es que no hay forma de hacer esto sin replicar el proceso de instalación de uno u otro en mi Dockerfile.

Este es un caso en el que los argumentos a ciegas acerca de que esto no es necesario, ya que cada contenedor debería ser solo un servicio, obviamente, no se aplican. Mi "servicio único" combina la funcionalidad de Docker y Jenkins.

El hecho es que no hay forma de hacer esto sin replicar el proceso de instalación de uno u otro en mi Dockerfile.

Entonces, ¿quieres romper dos archivos docker en uno para no tener que copiar / pegar cosas?

Copiar / pegar es el equivalente a bifurcar en este caso. Lo que quiero hacer es evitar bifurcar un Dockerfile para no perderme las mejoras de seguridad / errores u otros cambios cuando invariablemente cambie más adelante.

No puedo simplemente pasar. Buscando una forma de distribuir los cambios a lo largo de una larga cadena de herencia de imágenes (más profunda que 2). Las etapas múltiples no parecen ser lo que aclara un problema. Tener una entidad que podría contener solo un bloque de directivas, lo que me permite incluirlo en todas mis imágenes heredadas, junto con la funcionalidad de la imagen base, parece una evolución racional.

Para aquellos que se preguntan cuál es la forma correcta de hacer esto, desde la perspectiva de Docker, tómese unos minutos para revisar:
https://github.com/floydhub/dockerfiles

Aquí crea un árbol completo de Dockerfiles. A medida que baja por el árbol, encontrará diferentes combinaciones de dependencias, cada una DESDE el nivel superior del árbol. Entonces, si seguiste el árbol desde
-ubuntu->common-deps->python3->deepLearningBase->pyTorch
y realmente querías

-ubuntu->common-deps->python3->deepLearningBase->pyTorch 
+
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow 

Todo lo que haría es agregar un nodo (carpeta) en deepLearningBase para ambos, por ejemplo
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow-pyTorch

Ahora, todavía tienes que crear un dockerfile que combine pyTorch y TensorFlow dockerfiles, pero
la clave es que esos archivos serán MUY SIMPLES, solo un par de líneas de instalación además de deepLearningBase.

Entonces, lo que realmente se necesita es para varios repositorios de github a gran escala como este, para diferentes "mundos", como desarrollo web, aprendizaje profundo, software integrado, etc.

Luego, simplemente seguiría el árbol hasta su compilación requerida, y si nadie más lo hizo todavía, simplemente agregue un nodo y combine 2 o 3 líneas apt-get y cree su nuevo entorno.

Parece el estilo de composición de "elige tu propia aventura". INCLUIR sería mucho más sencillo. Demonios, solo quiero componer una imagen gcc especificada con nano para no tener que instalar nano desde apt-get cada vez.

Estoy de acuerdo con @chambm en su comentario anterior. No hay ninguna razón por la que esto no debería ser posible en la mayoría de los casos (los conflictos deberían ser bastante raros, ya que se encuentran en sistemas operativos administrados manualmente).

Este es un caso de uso bastante similar al que comentó @cloutiertyler , donde no se aplican ni la solución de @franklinyu , ni las compilaciones de múltiples etapas comentadas por @ cpuguy83 :

donde:

  • Los pasos de A a C son exactamente los mismos que los de B a D (dockerfileAC).
  • El equipo de desarrollo de B no sabe nada sobre C, D o E.
  • El equipo de desarrollo de C no sabe nada sobre B, D o E.

Un usuario que desee compilar D (y / o E), debe tener acceso a dockerfileAC, pero no es necesario que conozca dockerfileAB. Por lo tanto, el usuario debe comprender mejor una dependencia (C) que la otra (B). Idealmente, debería ser posible confiar en los equipos A y B, y simplemente construir D como A + (diff(B,A) + diff(C,A)) (fusionar) o A + diff(B,A) + diff(C,A) (rebase).

Debido a que GHDL no es un servicio web y VUnit no es un cliente web, ambas herramientas deben instalarse en la misma imagen / contenedor (E). Las compilaciones de múltiples etapas no son útiles, porque necesitamos compilar un dockerfile (probablemente desconocido) con dos etiquetas FROM , no es una sola cadena de reenvío.

Si encuentra este caso de uso similar a la fusión / rebase de dos ramas de git: a veces no hay conflictos, a veces los conflictos se pueden resolver fácilmente, a veces no se puede fusionar en absoluto porque no hay un historial común ... ¿Hay alguna herramienta, ya sea oficial o externo, que proporciona esta característica? Tenga en cuenta que está bien si la herramienta solo exporta dos imágenes a las ramas de git y realmente usa git para la fusión.

Increíble, esto sigue siendo un problema y un tema. ¿Qué tan difícil es "INCLUIR alguna imagen", luego, al analizarla, verifique que la base sea compatible (en la cadena FROM) y, de ser así, ejecute el resto de ESE archivo en ese punto (como si hubiera copiado el Dockerfile del proyecto? y lo pegué en el mío)?

Toda la excusa de "la gente hará cosas malas de las que no se da cuenta" es absurda en este contexto. Esto ya es increíblemente complejo y por eso lo necesitamos para ayudar a simplificarlo.

@rainabba Este es un comentario completamente inútil.
Básicamente, hay dos razones por las que no se hace:

  1. No es así de fácil
  2. Nadie se ha tomado el tiempo de hacer el trabajo.

En realidad, suele ser ambos.

  1. Es un problema de análisis y reemplazo de cadenas que cualquier codificador nuevo podría lograr en 10 minutos SI supieran en qué parte del código. No estoy diciendo que sea utilizable en todos los casos, pero para los casos limitados que veo sugeridos aquí una y otra vez (donde las bases son efectivamente comunes), es un timbre muerto.

  2. Por supuesto que no, este hilo proporciona ~ 102 razones por las que no se puede o no se debe hacer, entonces, ¿por qué alguien pensaría en hacerlo de todos modos?

Por otro lado, mi comentario sirve (como muchos otros aquí) para demostrar que existe la necesidad y la esperanza de influir en las actitudes obstructoras o al menos actuar como un recordatorio. Si eso es "completamente inútil", entonces acaba de explicar por qué este problema (solicitud de función ignorada) todavía está aquí y activo y no es técnico.

Es mucho más que analizar una cadena.
Millones de personas utilizan Docker y Dockerfile. Agregar API es algo importante ... incluso fuera de eso, la implementación subyacente no es "analizar una cadena".

En cualquier caso hay muchas propuestas para solucionar el problema y este es un tema muy antiguo y cerrado.

Creo que si Docker no encuentra una solución limpia para este escenario, probablemente será reemplazada por cualquier herramienta que lo resuelva.

Noté que uno de mis colegas usaba el siguiente patrón, que podría ser una solución decente:

ARG from
FROM $from
... rest of dockerfile

Sin embargo, no lo he probado yo mismo, así que no estoy seguro de cómo funcionaría en la práctica, por ejemplo, cómo se comporta con el almacenamiento en caché, etc.

De hecho, este es un problema muy importante y no se ha abordado adecuadamente. Me sorprende que una empresa tan grande como Docker no lo haya abordado todavía.

Solo mis dos centavos ... Estoy aprendiendo más sobre Docker en este momento y siento que algo como INCLUDE sería muy útil. Me gustó el ejemplo de herencia múltiple anterior y quería abordar los comentarios sobre posibles problemas y conflictos con él.

La herencia múltiple es difícil en cualquier idioma que la admita, pero cuando ocurre un conflicto es responsabilidad del creador del archivo Docker repensar lo que están haciendo y comenzar de nuevo. Docker debería simplemente compilar la imagen y no intentar demostrar que la compilación no tiene problemas.

@cosminonea

Siento que algo como INCLUIR sería muy útil

Tengo soporte para macros en https://github.com/larytet/dockerfile-generator/ También podría admitir "incluir".

Eso sería perder el punto. El objetivo no es incluir el Dockerfile
definición. El objetivo es incluir la imagen de la ventana acoplable. Esto va a
parece absurdo porque está fuera de mi cabeza:

de fedora
incluir ubuntu / ubuntu
incluir debian / debian

Razonablemente, esperaría que esto comenzara con la imagen de fedora.
Luego agregue la imagen para ubuntu en la carpeta / ubuntu. Luego agregó el
imagen para debian bajo / debian.

Por supuesto, esto es absurdo, ya que ¿por qué quiero mezclar un montón de
sistemas en una imagen? Pero un ejemplo más útil podría ser:

de fedora
incluir plex / plex
incluir commericalremover / plex / add-on / commericalremover

Ahora en este caso tiene más sentido. En que si estas son otras imagenes
no tengo componentes operativos específicos, tengo una manera fácil de hacer las cosas
modular.

El miércoles 8 de agosto de 2018 a las 15:48, Arkady Miasnikov [email protected]
escribió:

Siento algo como INCLUIR
Tengo soporte para macros en
https://github.com/larytet/dockerfile-generator/ Podría agregar "incluir"
apoyo también.

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/3378#issuecomment-411529506 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/ADBcWAtBDEp_LXpW3HUkHd3Pw5IVAXvqks5uO0ChgaJpZM4BWkJ9
.

Ese último ya es posible; COPY --from acepta tanto una etapa de construcción como una imagen, por ejemplo;

FROM busybox

COPY --from=alpine:latest / /
COPY --from=docker:latest /usr/local/bin/docker /usr/local/bin/

Editar; o para tomar el ejemplo real;

FROM fedora

COPY --from=ubuntu:latest / /ubuntu/
COPY --from=debian:latest / /debian/

Exactamente. Por eso consideraría la actualización de 2017 que agregó "COPIA
- de "por haber completado la solicitud original. Hay absolutamente
nada más estaba buscando en este boleto.

Las ideas que surgieron más tarde, como la modificación automática de la inclusión, serían
bonitas características. Pero van más allá de la pregunta original.

Saludos,

Factura

El jueves 9 de agosto de 2018 a las 12:55, Sebastiaan van Stijn [email protected]
escribió:

Ese último ya es posible; COPY: acepta tanto una
etapa de construcción, o una imagen, por ejemplo;

DESDE busybox

COPIA --desde = alpine: último / /
COPIA --desde = docker: último / usr / local / bin / docker / usr / local / bin /

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/3378#issuecomment-411824851 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/ADBcWPE738cs9xf3ZHSOaUd1foI1XVIQks5uPGmYgaJpZM4BWkJ9
.

@thaJeztah El uso de

Por supuesto, fusionar imágenes de Docker no es trivial. Dado que se pueden ejecutar scripts arbitrarios durante las compilaciones, el proceso de compilación resiste cualquier intento general de detección automática de conflictos; el problema que se detiene dice hola! Lo mejor que puede hacer (salvo limitar significativamente lo que pueden hacer las compilaciones) es definir una semántica precisa: digamos que el último FROM / INCLUDE gana (por ejemplo, si "escriben" el mismo archivo) o fallará en un conflicto a nivel del sistema de archivos o ....

El problema a veces mencionado de diferentes imágenes "base" (stretch vs ubuntu vs alpine vs ...), sin embargo, _ es_ simple: requiere que el DAG de dependencias de imágenes no solo tenga una fuente única (la imagen actual) sino también un sumidero único (el "antepasado" compartido de todas las imágenes en la "jerarquía").

En última instancia, por supuesto, obtendría basura dentro-basura - ¿es realmente diferente alguna vez?

FWIW, mis casos de uso son:

  1. Ejecución de una aplicación web Tomcat con una base de datos PostgreSQL y un almacén de objetos S3.
    Si bien esto se puede resolver usando Docker Compose, un solo contenedor puede ser mejor.
  2. Las compilaciones en varios idiomas se ejecutan en contenedores Docker (por ejemplo, en Jenkins, Circle CI, ...).
    Hay imágenes oficiales para las cadenas de herramientas más populares, pero conseguir un solo contenedor equipado para manejar más de una ejecución es exactamente el tema que se analiza aquí.

@reitzig Esta no es la única opción. La opción correcta es restringir INCLUDE para evitar grandes problemas. INCLUDE no puede heredar. Ahí está. Simple. Sigue siendo increíblemente útil.

Esta solicitud de función es popular, pero Docker es gratuito como en Beer, pero no gratuito de ningún modo como en Freedom.

@rjurney Con la inclusión del soporte de buildkit desde 18.06, los usuarios pueden proporcionar su propio analizador de frontend para el constructor. Ya existe un analizador de Dockerfile experimental oficial (de Docker Inc) que incluye muchas características nuevas (soporte para secretos para principiantes).

Por supuesto, también puede agregar su propio comportamiento "INCLUDE" en una interfaz personalizada de Dockerfile, o puede hacer algo totalmente diferente que no sea Dockerfile (hay un ejemplo para buidpacks).

Para usar una interfaz personalizada, solo necesita apuntar a Docker a una imagen que pueda manejarla. Haga esto como un comentario en la primera línea de su Dockerfile (o lo que sea) syntax = myCustomFrontendImage

Más detalles aquí:
https://docs.docker.com/develop/develop-images/build_enhancements/#overriding -default-frontends

Con buildkit habilitado, Docker puede construir lo que quiera (ni siquiera tiene que ser un formato de Dockerfile) con las características que necesite.

Esta solicitud de función es popular, pero Docker es gratuito como en Beer, pero no gratuito de ningún modo como en Freedom.

Por más fuera de tema que sea esa nota, creo que debe tenerse en cuenta que estás equivocado. Gracias a las licencias Apache de Docker, todos tienen la libertad de bifurcar y desarrollar su propio intérprete para Dockerfiles que proporciona las funciones desarrolladas aquí. Si tienen cuidado, las imágenes resultantes serán compatibles con los tiempos de ejecución / herramientas de Docker existentes.
Por supuesto, los mantenedores del proyecto Docker son igualmente libres de no fusionar dicha característica en su bifurcación (¿la original?).

@reitzig Eso es obviamente una perorata sin sentido sin hacer referencia a lo que es software libre. Moby es un software gratuito, por supuesto.

No sabía que ahora tenía licencia de Apache. Pido disculpas por el comentario y
creo que esto es genial!

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

El miércoles 16 de enero de 2019 a las 4:17 a. M., Raphael R. [email protected] escribió:

Esta solicitud de función es popular, pero Docker es gratuito como en Beer, pero no por
cualquier medio Libre como en Libertad.

Tan fuera de tema como es esa nota, creo que debe tenerse en cuenta que estás
incorrecto. Gracias a las licencias Apache de Docker, todo el mundo tiene la libertad de
bifurcar y desarrollar su propio intérprete para Dockerfiles que proporciona la
características desarrolladas aquí. Si tienen cuidado, las imágenes resultantes serán
compatible con los tiempos de ejecución / herramientas de Docker existentes.
Por supuesto, los mantenedores del proyecto Docker son igualmente libres de no
fusionar una característica de este tipo en su bifurcación (¿el original?).

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/3378#issuecomment-454758482 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

Lo siento, no dormí bien y cometí un error. Mi comentario se mantiene.
Libre como en Beer significa Apache. Libre como en Libertad significa control comunitario.
Un proyecto de Apache o alguna otra forma de gobierno.

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

El miércoles 16 de enero de 2019 a las 12:32 p.m. Russell Jurney [email protected]
escribió:

No sabía que ahora tenía licencia de Apache. Pido disculpas por el comentario y
creo que esto es genial!

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

El miércoles 16 de enero de 2019 a las 4:17 a. M. Raphael R. [email protected]
escribió:

Esta solicitud de función es popular, pero Docker es gratuito como en Beer, pero no por
cualquier medio Libre como en Libertad.

Tan fuera de tema como es esa nota, creo que debe tenerse en cuenta que estás
incorrecto. Gracias a las licencias Apache de Docker, todo el mundo tiene la libertad de
bifurcar y desarrollar su propio intérprete para Dockerfiles que proporciona la
características desarrolladas aquí. Si tienen cuidado, las imágenes resultantes serán
compatible con los tiempos de ejecución / herramientas de Docker existentes.
Por supuesto, los mantenedores del proyecto Docker son igualmente libres de
no fusionar tal característica en su bifurcación (¿el original?).

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/3378#issuecomment-454758482 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

Libre como en Beer significa Apache.

Discrepar. El software gratuito puede ser software propietario.

Libre como en Libertad significa control comunitario.

¿Qué es el control comunitario? ¿Proyectos gestionados por una fundación? Entonces, ¿consideraría VS Code, Atom editor y Ubuntu como software no libre? Entonces, su definición es significativamente diferente de la propuesta por FSF, EFF y muchas otras organizaciones.

Estoy de acuerdo en que Docker Inc no está discutiendo activamente con la comunidad sobre este tema, pero esto no tiene nada que ver con "Free as in Freedom".

Lo siento amigos, no tengamos este tipo de discusiones sobre el rastreador de problemas.

Estoy de acuerdo en que Docker Inc no está discutiendo activamente con la comunidad sobre este tema.

Hemos hecho posible la compatibilidad con cualquier formato de compilación que desee tener a través de docker build . El formato "oficial" de Dockerfile no admite esta opción, pero eso no significa que docker build no pueda utilizarlo.
Consulte https://matt-rickard.com/building-a-new-dockerfile-frontend/ como un ejemplo de cómo crear una interfaz personalizada que funcione con docker build .
Tenga en cuenta que esta interfaz es un ejemplo de cómo puede hacer algo completamente diferente al formato Dockerfile, pero eso no es necesario. Puede tomar el formato de Dockerfile existente y agregar su propia funcionalidad si lo desea.

En cuanto a agregar algo al formato oficial de Dockerfile ... Diré que las propuestas siempre son bienvenidas, el formato se mantiene en https://github.com/moby/buildkit.
Sin embargo, tenga en cuenta que cada característica nueva significa una nueva carga de mantenimiento, lo que a menudo incluye la limitación de lo que se puede hacer en el futuro.

Creo que es probable que muchos de los casos de uso para combinar múltiples Dockerfiles realmente se puedan resolver con una nueva funcionalidad en Dockerfile ... específicamente la capacidad de COPY --from y RUN --mount partir de imágenes arbitrarias.

Si este INCLUDE hipotético pudiera simplemente crear los contenedores adicionales como un detalle implícito sin que yo tuviera que dar un @ # $%, reduciría en gran medida la cantidad de frustración que rodea el argumento de venta implícito y dudoso de los contenedores componibles. Realmente solo quiero volver a la aplicación y ofrecer funcionalidad. Perdón por las malas vibraciones, pero soy un novato en la ventana acoplable / contenedor y me encontré con la misma confusión que muchos otros carteles ya han expresado.

¿Y si pudieras hacer esto?

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   custom image (with both python and rust)
             \                                 /
              \----- rust:1.44-alpine3.12 ----/

_Nótese que ambas imágenes son descendientes de la misma imagen. ¡Esta es la clave! _

Tan fácilmente como esto:

FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

_Comparado con el uso de la instrucción "COPIA --desde la imagen" (compilaciones de varias etapas), no tendrá que pensar en los detalles de implementación (qué archivos / variables de entorno copiar) ._

Cómo se ve ahora mismo si desea combinar las imágenes

FROM alpine:3.12.0

# INCLUDE rust:1.44-alpine3.12
COPY --from=rust:1.44-alpine3.12 / /
ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=1.44.1

# INCLUDE python:3.8.3-alpine3.12
COPY --from=python:3.8.3-alpine3.12 / /
ENV PATH /usr/local/bin:$PATH
ENV LANG C.UTF-8
ENV GPG_KEY E3FF2839C048B25C084DEBE9B26995E310250568
ENV PYTHON_VERSION 3.8.3
ENV PYTHON_PIP_VERSION 20.1.1
ENV PYTHON_GET_PIP_URL https://github.com/pypa/get-pip/raw/eff16c878c7fd6b688b9b4c4267695cf1a0bf01b/get-pip.py
ENV PYTHON_GET_PIP_SHA256 b3153ec0cf7b7bbf9556932aa37e4981c35dc2a2c501d70d91d2795aa532be79

_Las instrucciones ENV se copian y pegan de los archivos Docker de estas imágenes.


Esto también permitiría una reutilización de contenedores mucho mejor, y haría extremadamente fácil juntar cosas que de otra manera podrían llevar años compilarlas o construirlas usted mismo.

Tenga en cuenta que con este enfoque, un programa solo necesita compilarse una vez por plataforma / versión de imagen base, y es más fácil de reutilizar, en lugar de implementarlo usted mismo. Piense en cuántas veces se ha reimplementado la "rueda" en C ++ debido a la falta de un administrador de paquetes bueno / universal. ¿Queremos que surja una situación similar para Docker?

@bergkvist , consulte https://github.com/moby/moby/issues/3378#issuecomment -381449355 y https://github.com/moby/moby/issues/3378#issuecomment -381641675.

Me parece que ninguna de las soluciones que propones se corresponde con el diagrama. En cambio, estás haciendo:

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   \
             \                                   \
              \----- rust:1.44-alpine3.12 --------\ custom image 

Por lo tanto, Python sobrescribe cualquier archivo que se haya modificado en rust . Combinarlos sin copiar uno sobre el otro requeriría algunas fusiones.

@eine Sí, en caso de conflicto, los archivos se sobrescribirán. Eso es cierto. Por lo tanto, la figura que es simétrica sería un caso especial en el que no se superponen archivos (relevantes). Tu versión de la figura es más general.

Mi punto acerca de que ambas imágenes hereden de la misma imagen exacta es que la posibilidad de conflictos críticos puede ser mínima.

Me imagino que podrían surgir algunos conflictos relacionados con los archivos del administrador de paquetes. Si ambas imágenes usaron el administrador de paquetes para instalar cosas diferentes. No estoy seguro de si hay otros "conflictos comunes" como ese que podrían manejarse con algún tipo de caso especial.

Combinar dos archivos no es nada sencillo. Creo que en el caso general, sería mejor simplemente sobrescribir que tratar de ser inteligente. Al menos entonces es más fácil depurar cuando las cosas no funcionan.

Desde que comenté aquí hace 4 días, decidí aprender Golang y buscar en el código frontend para el código moby / buildkit.

Ahora he creado una interfaz personalizada que acepta declaraciones INCLUDE como mencioné anteriormente.

#syntax=bergkvist/includeimage
FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

Para usar la sintaxis personalizada, recuerde configurar DOCKER_BUILDKIT = 1 al construir.

DOCKER_BUILDKIT=1 docker build -t myimage .

El código está disponible aquí: https://github.com/bergkvist/includeimage
E imagen en Docker Hub: https://hub.docker.com/r/bergkvist/includeimage

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