Moby: tiempo de compilación solo opción -v

Creado en 21 jun. 2015  ·  258Comentarios  ·  Fuente: moby/moby

Según lo sugerido por @ cpuguy83 en https://github.com/docker/docker/issues/3156
aquí está el caso de uso para una opción flexible -v en el momento de la compilación.

Al crear una imagen de Docker, necesito instalar una base de datos y una aplicación. Todo está envuelto en dos tarballs: 1 para la base de datos y 1 para la aplicación que debe instalarse en ella (esquema, objetos, datos estáticos, credenciales, etc.). Luego, toda la solución se ejecuta a través de un script de shell que maneja varias variables de shell y ajusta las credenciales del sistema operativo y otras cosas en consecuencia.
Cuando exploto el tarball anterior (o uso la directiva ADD de Dockerfile), todo aumenta hasta aproximadamente 1.5 GB (!). No es ideal como puedes imaginar.

Me gustaría tener esta directiva '-v /distrib/ready2installApp:/distrib' todavía posible (como está hoy en Dockerfile)
pero

Me gustaría desasociar el proceso de compilación declarativo (infraestructura como código) del artefacto desplegable en tiempo de ejecución del contenedor. No quiero tener que lidiar con el peso muerto de 1,5 GB que no necesito.

¿Podríamos tener una opción --unmount-volume que pueda ejecutar al final del Dockerfile?
o
Teniendo en cuenta cómo funciona Volumen en este momento en un Dockerfile, ¿quizás necesitemos una nueva directiva de Dockerfile para un volumen temporal que la gente usa durante la instalación? Creo que el ejemplo de Puppet proporcionado por @fatherlinux estaba en una línea similar...
o
Lo que se les ocurra.
El objetivo es evitar tener que cargar con todo ese peso muerto que no sirve para una App o Servicio desplegado. Sin embargo, ese peso muerto es necesario @install-time. Not Everybody tiene una simple "instalación yum" de los repositorios oficiales. :)

Muchísimas gracias

arebuilder kinfeature

Comentario más útil

Tengo un caso de uso ligeramente diferente para esta característica: paquetes de almacenamiento en caché que son descargados/actualizados por el administrador de paquetes ASP.Net 5 . El administrador de paquetes administra su propia carpeta de caché, por lo que, en última instancia, solo necesito una carpeta que pueda reutilizar entre compilaciones.

Es decir:

docker build -v /home/dokku/cache/dnx/packages:/opt/dnx/packages -t "dokku/aspnettest" .

Todos 258 comentarios

Estoy buscando una solución similar.

Problema

Recientemente, la empresa en la que trabajo habilitó el proxy Zscaler con inspección SSL, lo que implica tener certificados instalados y algunas variables de entorno configuradas durante la compilación.

Una solución temporal fue crear un nuevo Dockerfile con certificados y variables de entorno establecidas. Pero eso no parece razonable, en una visión a largo plazo.

Entonces, mi primer pensamiento fue configurar un proxy transparente con HTTP y HTTPS, pero nuevamente necesito pasar un certificado durante la compilación.

El escenario ideal es con el mismo Dockerfile, podría crear mi imagen en mi computadora portátil, en casa y en la empresa.

Solución posible

# Enterprise
$ docker build -v /etc/ssl:/etc/ssl -t myimage .

# Home
$ docker build -t myimage .

Tengo un caso de uso ligeramente diferente para esta característica: paquetes de almacenamiento en caché que son descargados/actualizados por el administrador de paquetes ASP.Net 5 . El administrador de paquetes administra su propia carpeta de caché, por lo que, en última instancia, solo necesito una carpeta que pueda reutilizar entre compilaciones.

Es decir:

docker build -v /home/dokku/cache/dnx/packages:/opt/dnx/packages -t "dokku/aspnettest" .

@yngndrw lo que propones también estaría bien para mí, es decir, necesitamos montar recursos adicionales en el momento de la compilación que no serían necesarios en el momento de la ejecución, ya que se han instalado en el contenedor.

FWIW Vi en algún lugar de estas páginas a alguien diciendo algo como (y espero estar parafraseándolo bien) "resuelva su problema de compilación en una máquina host similar y luego simplemente instale el artefacto desplegable o exe en el contenedor".
Me temo que no es tan simple chicos. A veces, necesito instalar en /usr/bin pero también necesito editar algún archivo de configuración. Compruebo el sistema operativo en el que me estoy ejecutando, los parámetros del kernel que necesito ajustar, los archivos que necesito crear según las variables o los archivos de compilación del manifiesto. Hay muchas dependencias que simplemente no están satisfechas con una simple copia de un producto compilado.

Reafirmo lo que dije cuando abrí el problema: hay una diferencia entre un archivo de declaración de manifiesto y su proceso y el tiempo de ejecución de un artefacto.
Si realmente creemos en la infraestructura como código y, además, en la infraestructura inmutable, que Docker mismo está promoviendo más y me gusta por cierto, entonces esto debe considerarse seriamente en mi opinión (ver la hinchazón en la publicación 1 adjunta)

Gracias de nuevo

Otro caso de uso realmente interesante es la actualización de software. Hay momentos, como con FreeIPA, en los que realmente debería probar con una copia de los datos de producción para asegurarse de que todos los diferentes componentes puedan actualizarse sin problemas. Todavía desea realizar la actualización en un entorno de "construcción". Desea que la copia de producción de los datos viva en otro lugar para que cuando mueva las nuevas versiones actualizadas de los contenedores a producción, puedan acumular los datos exactos en los que realizó la actualización.

Otro ejemplo sería Satellite/Spacewalk, que cambia de esquema con frecuencia e incluso cambió las bases de datos de Oracle a Postgresql en la versión 5.6 (IIRC).

Hay muchos, muchos escenarios en los que necesito acceder temporalmente a los datos mientras realizo una actualización de software en una compilación en contenedores, especialmente con microservicios/distribuidos...

Esencialmente, ahora me veo obligado a hacer una actualización manual ejecutando un contenedor regular con un montaje de enlace -v, luego haciendo una "confirmación de ventana acoplable". No puedo entender por qué la misma capacidad no estaría disponible con una compilación automatizada de Dockerfile.

Secundando a @yngndrw señalando el almacenamiento en caché: exactamente el mismo razonamiento se aplica a muchos proyectos populares como Maven, npm, apt, rpm: permitir un caché compartido puede acelerar drásticamente las compilaciones, pero no debe llegar a la imagen final.

Estoy de acuerdo con @stevenschlansker. Puede haber muchos requisitos para adjuntar el volumen de caché, o algún tipo de gigabytes de datos, que deben presentarse (en estado analizado) en la imagen final, pero no como datos sin procesar.

También me ha mordido la resistencia constante a extender docker build para respaldar los volúmenes que pueden usar docker run . No he encontrado que el mantra de 'compilaciones independientes del host' sea muy convincente, ya que solo parece hacer que el desarrollo y la iteración de las imágenes de Docker sean más difíciles y lentos cuando necesita volver a descargar el repositorio de paquetes completo cada vez que reconstruye una imagen.

Mi caso de uso inicial fue el deseo de almacenar en caché los repositorios de paquetes del sistema operativo para acelerar la iteración del desarrollo. Una solución alternativa que he estado usando con cierto éxito es similar al enfoque sugerido por @fatherlinux , que es simplemente dejar de luchar con docker build y Dockerfile por completo, y comenzar desde cero usando docker run en un script de shell estándar seguido de docker commit .

Como un pequeño experimento, amplié mi técnica en un reemplazo completo para docker build usando un poco de secuencias de comandos de shell POSIX: dockerize .

Si alguien quiere probar este script o el enfoque general, hágamelo saber si es interesante o útil (o si le funciona). Para usarlo, coloque la secuencia de comandos en algún lugar de su RUTA y agréguela como un shebang para su secuencia de comandos de compilación (la cosa #! ), luego configure las variables de entorno relevantes antes de una segunda línea shebang que marque el inicio de su secuencia de comandos de instalación de Docker.

Las variables FROM , RUNDIR y VOLUME se pasarán automáticamente como argumentos a docker run .
Las variables TAG , EXPOSE y WORKDIR se pasarán automáticamente como argumentos a docker commit .

Todas las demás variables se evaluarán en el shell y se pasarán como argumentos de entorno a docker run , haciéndolos disponibles dentro de su secuencia de comandos de compilación.

Por ejemplo, este script almacenará en caché y reutilizará los paquetes de Alpine Linux entre compilaciones (el VOLUMEN monta un directorio de inicio en CACHE, que luego se usa como un enlace simbólico para el caché del repositorio de paquetes del sistema operativo en el script de instalación):

#!/usr/bin/env dockerize
FROM=alpine
TAG=${TAG:-wjordan/my-image}
WORKDIR=/var/cache/dockerize
CACHE=/var/cache/docker
EXPOSE=3001
VOLUME="${HOME}/.docker-cache:${CACHE} ${PWD}:${WORKDIR}:ro /tmp"
#!/bin/sh
ln -s ${CACHE}/apk /var/cache/apk
ln -s ${CACHE}/apk /etc/apk/cache
set -e
apk --update add gcc g++ make libc-dev python
[...etc etc build...]

Entonces, después de reunirme con el contingente francés :) de Docker en MesoCon la semana pasada (fue un placer, muchachos), me di cuenta de que tenían el mismo problema internamente y desarrollaron un truco que copia lo que necesitan en una nueva imagen delgada. .
Diría que los hacks no son bienvenidos en el mundo empresarial;) y esta solicitud debe manejarse adecuadamente.
Gracias por escuchar chicos...

También estoy a favor de agregar el indicador -v de tiempo de compilación para acelerar las compilaciones al compartir un directorio de caché entre ellos.

@yngndrw No entiendo por qué cerró dos problemas relacionados. Leí su número 59 y no veo cómo se relaciona esto con esto. En algunos casos, los contenedores se vuelven súper hinchados cuando no se necesitan en tiempo de ejecución. Por favor lea la 1ra publicación.
Espero no estar perdiéndome algo aquí... ya que ha sido un día largo :-o

El problema de @zrml https://github.com/aspnet/aspnet-docker/issues/59 estaba relacionado con el almacenamiento en caché integrado por capa que docker proporciona durante una compilación para todos los archivos de docker, pero este problema actual es sutilmente diferente ya que estamos hablando de usar volúmenes de host para proporcionar un almacenamiento en caché específico de dockerfile que depende de que el dockerfile haga un uso especial del volumen. Cerré el problema https://github.com/aspnet/aspnet-docker/issues/59 ya que no está específicamente relacionado con el proyecto/repositorio aspnet-docker.

El otro problema al que creo que te refieres es el problema https://github.com/progrium/dokku/issues/1231 , que se refería a los procesos de Dokku que deshabilitaban explícitamente el almacenamiento en caché de la capa docker incorporada. Michael hizo un cambio en Dokku para permitir que este comportamiento fuera configurable y esto resolvió el problema con respecto al proyecto/repositorio de Dokku, por lo que ese problema también se cerró.

Es posible que todavía haya un problema relacionado con Docker que esté pendiente (es decir, ¿por qué Docker no estaba manejando el almacenamiento en caché de la capa integrada como esperaba en el problema https://github.com/aspnet/aspnet-docker/issues/59), pero No he tenido la oportunidad de averiguar por qué es eso y confirmar si todavía está sucediendo. Si sigue siendo un problema, se debe plantear un nuevo problema para este proyecto/repositorio, ya que es distinto de este problema actual.

@yngndrw exactamente, así que estamos de acuerdo en que esto es diferente y conocido en @docker.com, así que lo reabriré si no le importa... bueno, no puedo. ¿Te importa, por favor?
Me gustaría ver algunos comentarios de nuestros colegas en SF al menos antes de cerrarlo.

Por cierto, @cpuguy83 me pidió que abriera un caso de usuario y lo explicara todo, desde el registro n.º 3156

@zrml No estoy seguro de seguir - ¿Es https://github.com/aspnet/aspnet-docker/issues/59 que desea volver a abrir? No es un problema de /aspnet/aspnet-docker, por lo que no creo que sea correcto volver a abrir ese problema. Realmente debería ser un problema nuevo en/docker/docker, pero necesitaría ser verificado y necesitaría pasos reproducibles para generar primero.

no, no.. este #14080 que cerraste ayer.

¿Este tema sigue abierto?

@yngndrw Creo que leí mal el ícono rojo "cerrado". Disculpas.

Totalmente de acuerdo en que build time -v sería de gran ayuda.

El almacenamiento en caché de compilación es un caso de uso.

Otro caso de uso es el uso de claves ssh en el momento de la compilación para compilar desde repositorios privados sin que se almacenen en la capa, lo que elimina la necesidad de hacks (aunque bien diseñados) como este: https://github.com/dockito/vault

Estoy comentando aquí porque esto es un infierno en un mundo corporativo.
Tenemos un proxy de interceptación SSL, aunque puedo dirigir el tráfico a través de él, muchos proyectos asumen que tienen buenas conexiones SSL, por lo que mueren horriblemente.

Aunque mi máquina (y, por lo tanto, el generador de la ventana acoplable) confía en el proxy, las imágenes de la ventana acoplable no lo hacen.
Peor aún, la mejor práctica ahora es usar curl dentro del contenedor, por lo que es doloroso, tengo que modificar los Dockerfiles para que incluso se construyan. Podría montar los certificados con una opción -v y ser feliz.

Dicho esto. Es menos culpa de Docker, más culpa de los administradores de paquetes que usan https cuando deberían usar un sistema similar a cómo funciona apt-get. Como eso todavía es seguro y verificable, y también se puede almacenar en caché mediante un proxy http.

@btrepp gracias por otro buen caso de uso.

Puedo pensar en otra situación.

Una de las cosas que me gustaría hacer con mis archivos acoplables es no enviar las herramientas de compilación con el archivo acoplable "compilado". No hay ninguna razón por la que una aplicación C necesite gcc, ni una aplicación Ruby necesite un paquete en la imagen, pero si usa la compilación de Docker actualmente mientras tiene esto.

Una idea que he tenido es especificar un dockerfile, que ejecuta múltiples comandos de docker cuando se construye dentro de él. Psuedo-ish dockerfiles a continuación.

Archivo Docker que construye otros

FROM dockerbuilder
RUN docker build -t docker/builder myapp/builder/Dockerfile
RUN docker run -v /app:/app builder
RUN docker build -t btrepp/myapplication myapp/Dockerfile

btrepp/myapplication dockerfile

FROM debian:jessie+sayrubyruntime
ADD . /app //(this is code thats been build using the builder dockerfile
ENTRYPOINT ["rails s"]

Aquí tenemos un contenedor temporal que realiza toda la administración de paquete/instalación y cualquier script de compilación, pero produce los archivos que necesita el contenedor de tiempo de ejecución.

El contenedor de tiempo de ejecución simplemente agrega los resultados de esto, lo que significa que no debería necesitar mucho más que Ruby instalado. En el caso de, por ejemplo, GCC o, mejor aún, un enlace estático, es posible que no necesitemos nada más que los archivos del sistema operativo principal para ejecutar.

Eso mantendría las imágenes de Docker súper ligeras.

El problema aquí es que el contenedor del constructor temporal desaparecería al final, lo que significa que sería muy costoso sin la capacidad de cargar una especie de caché, estaríamos tomando debian:jessie un montón de veces.

He visto personas con ciertas técnicas como esta, pero usando servidores http externos para agregar los archivos de compilación. Preferiría mantenerlo todo construido por Docker. Aunque posiblemente haya una forma de usar una imagen acoplable para hacer esto correctamente. Usando run y así poder montar volúmenes.

Aquí hay otro ejemplo. Digamos que quiero construir un contenedor para systemtap que tenga todos los símbolos de depuración para el kernel (que son Yuuuuge). Tengo que montar los módulos /lib/subyacentes para que el comando yum sepa qué RPM instalar.

Además, tal vez preferiría tener estos en vivo en otro lugar que no sea la imagen de 1,5 GB (de los símbolos de depuración)

Fui a escribir un Dockerfile, luego me di cuenta de que era imposible :-(

docker run --privileged -v /lib/modules:/lib/modules --tty=true --interactive=true rhel7/rhel-tools /bin/bash
yum --enablerepo=rhel-7-server-debug-rpms install kernel-debuginfo-$(uname -r) kernel-devel-$(uname -r)
docker ps -a
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                        PORTS               NAMES
52dac30dc495        rhel7/rhel-tools:latest   "/bin/bash"         34 minutes ago      Exited (0) 15 minutes ago                         dreamy_thompson
docker commit dreamy_thompson stap:latest

https://access.redhat.com/solutions/1420883

Me gustaría repetir mi caso de uso aquí desde el n.° 3949, ya que ese error se cerró por otros motivos.

Realmente me gustaría aislar el software propietario en Docker. Es ilegal para mí alojarlo en cualquier lugar, y el proceso de descarga no se puede automatizar de manera realista (o legal). En total, los instaladores llegan a unos 22 GB (y se hacen más grandes con cada versión). Creo que es una tontería esperar que esto se copie en la imagen de la ventana acoplable en el momento de la compilación.

¿Alguna novedad en esta característica necesaria?
gracias

_ENCUESTA DE USUARIOS_

_La mejor manera de recibir una notificación cuando haya cambios en esta discusión es haciendo clic en el botón Suscribirse en la parte superior derecha._

Las personas que se enumeran a continuación han apreciado su discusión significativa con un +1 aleatorio:

@vad

¡+1 por esta característica!

Otro caso de uso es el uso de claves ssh en el momento de la compilación para compilar desde repositorios privados sin que se almacenen en la capa, lo que elimina la necesidad de hacks (aunque bien diseñados) como este: https://github.com/dockito/vault

Este es nuestro caso de uso también (claves ssh procesadas usando tmpfs en el host en este caso).

Otro caso de uso para esto es para un caché local del directorio node_modules en un servidor CI para reducir los tiempos de compilación.
npm install es muy lento e incluso en el "mejor" caso actual donde package.json es ADD ed a la imagen, npm install se ejecuta y solo entonces se las fuentes reales del proyecto se agregaron y se basaron en los cambios a package.json todas las dependencias deben volver a descargarse.

Consulte npm/npm#8836 para ver un problema sobre esto en el lado de Node/npm.

Problema relacionado con aspnet-docker con respecto a la restauración lenta de paquetes y el tamaño de imagen resultante del almacenamiento en caché de los paquetes actuales en la capa. Sería mucho mejor usar un volumen montado para el almacenamiento en caché del paquete.
https://github.com/aspnet/aspnet-docker/issues/123

Este no es un problema específico del idioma, afectará a muchas personas dado que los administradores de paquetes ahora son un estándar aceptado.

El OP ha solucionado el problema en la cabeza, ya que "docker build -v" ayudaría enormemente a desacoplar el proceso de compilación del entorno de tiempo de ejecución.

He visto varios proyectos que ahora construyen "puertos de Mulberry" que luego se usan para construir la ventana acoplable real que luego se empuja/distribuye. Esto es demasiado complejo tanto desde la perspectiva de la administración como de los recursos informáticos, lo que a su vez se traduce en pruebas unitarias y de CI más lentas y, en general, en un flujo de trabajo de desarrollo menos productivo.

He estado pensando en esto, y la otra opción que se me ocurre es la capacidad de marcar capas como capas "src".

Algo similar a esas capas solo es accesible durante una compilación de la ventana acoplable, pero no se extrae en el archivo de imagen resultante.

De esta manera, la ventana acoplable puede almacenar en caché capas/imágenes anteriores, artefactos de compilación temporales, pero estos no son necesarios para utilizar la imagen final.

P.ej.

FROM ubuntu
RUN apt-get install gcc
ADDPRIVATE . /tmp/src <--these can be cached by docker locally
RUNPRIVATE make     <-- basically these layers become scoped to the current build process/dockerfile
RUN make install <--result of this layer is required.

Por supuesto, esto significa que necesitaría saber mejor lo que está haciendo, ya que podría omitir archivos críticos.

@yngndrw
Una solución mucho mejor para situaciones como netcore sería que no usen HTTPS para la gestión de paquetes, entonces es trivial configurar iptables+squid para tener un proxy de almacenamiento en caché transparente para compilaciones de docker. Mi opinión personal es que estos administradores de paquetes deberían configurar su game, son terribles de usar en entornos corporativos debido a la renuncia de ssl, mientras que cosas como apt-get funcionan perfectamente bien y ya se pueden almacenar en caché con iptables+squid para docker.

También puedo ver una desventaja en el uso de volúmenes de tiempo de compilación, los archivos dockerfiles no serán tan reproducibles y requerirá una configuración adicional fuera de docker build -t btrepp/myapp. También hará que las compilaciones automatizadas en dockerhub sean difíciles.

@btrepp : Me gusta tu sugerencia. Incluso podría vivir para mis casos de uso con un directorio TMP codificado (sé que generalmente es algo malo) del que Docker nos habla para que sepan cuándo construyen el artefacto final de todas las capas que pueden olvidar/dejar de lado el uno montado en /this_is_the_tmp_explosion_folder_that_will_be_removed_from_your_final_container_image
Suficientemente fácil....

@btrepp Me gusta bastante tu idea de la capa de origen.

Sin embargo, con respecto a los administradores de paquetes que no usan SSL, tendría que estar en desacuerdo.

Si quisiera almacenar en caché paquetes como ese, entonces probablemente debería usar una fuente de paquete privado (local) que refleje la fuente oficial. Volver a HTTP me parece una mala idea, especialmente dado que muchos administradores de paquetes no parecen firmar sus paquetes y, por lo tanto, confían en HTTPS.

Hay una herramienta gramatical/rocker que se puede usar mientras este problema aún no se solucione.

@yngndrw

Mi punto es que el proxy local, etc. es un problema que se resolvió hace mucho tiempo. Los administradores de paquetes solo necesitan verificación, no necesitan privacidad. Usar https es una forma perezosa de proporcionar verificación, pero viene con el archivo adjunto de privacidad.

No hay ninguna razón por la que "super_awesome_ruby_lib" deba ser privado cuando se extrae a través de http(s). La mejor manera sería que las gemas de rubí tuvieran un llavero. O incluso una clave pública conocida, y para que firme paquetes. Así es más o menos cómo funciona apt-get, y permite que los proxies http estándar almacenen cosas en caché.

Con respecto a un feed de paquete privado local, la ventana acoplable ni siquiera es compatible con esto. No hay forma de deshabilitar el feed estándar y, con razón, lo pierde si el certificado https no está en el almacén de certificados. Estoy bastante seguro de que la ventana acoplable siempre quiere al menos verificar el feed principal al extraer imágenes también. Afaik, la implementación de Rocket/rkt iba a usar la firma + http para obtener imágenes de contenedores.

Si la motivación principal para los volúmenes de tiempo de compilación es solo el almacenamiento en caché de los paquetes, entonces creo que se debe presionar a los administradores de paquetes para que admitan mejor el almacenamiento en caché, en lugar de comprometer parte de la automatización/pureza de Docker actualmente.

Para ser claros, no estoy abogando por que los administradores de paquetes cambien a solo usar http y descartar https. Necesitan verificación de paquetes para prevenir ataques contra el hombre en el medio. Lo que no necesitan es el aspecto de privacidad usando https como una oferta de "seguridad para atrapar todo el mazo".

Esa es una visión muy estrecha. Le está pidiendo a todo el universo de administradores de paquetes que cambie su comportamiento para ajustarse a la prescripción de Docker de cómo creen que se construirán las aplicaciones.

También hay muchos otros ejemplos de por qué esto es necesario en este hilo. Decir "bueno, deberías cambiar la forma en que funcionan todas las herramientas que usas para crear tus aplicaciones" no elimina el problema, solo alejará a los usuarios.

(También estoy totalmente en desacuerdo con el archivo adjunto de Docker al registro público; preferiría prohibir el acceso al registro público y solo permitir que se use nuestro registro interno. Pero ese es un tema completamente diferente).

Para mí también necesito docker build -v .

En nuestro caso, queremos crear una imagen que consiste en una instalación preconfigurada del producto en cuestión, y el instalador tiene más de 2 GB . Al no poder montar un volumen de host, no podemos crear la imagen con el instalador aunque ya la hayamos descargado en el sistema operativo del host, para lo cual podemos usar varias herramientas/protocolos, digamos proxy con https cert/auth , o tal vez incluso bit torrent.

Como solución alternativa, tenemos que usar wget para volver a descargar el instalador durante docker build , que es un entorno muy restringido, mucho menos conveniente, consume más tiempo y es propenso a errores.

Además, debido a la flexibilidad de las opciones de instalación/configuración del producto, tiene mucho más sentido para nosotros enviar las imágenes con el producto preinstalado, en lugar de enviar una imagen simplemente con el instalador.

@thaJeztah ¿ alguna posibilidad de que esto suceda?

Fwiw, esta es la única razón por la que no uso (o realmente no puedo) usar la ventana acoplable

Llevamos un parche en las versiones de Red Hat de docker que incluyen la opción -v. Pero la verdadera solución a esto sería crear formas nuevas y diferentes de crear imágenes de contenedores OCI además de la compilación de la ventana acoplable.

@rhatdan RHEL o Fedora?

También hemos implementado la opción -v de docker build en nuestra versión interna de docker en resin.io. Puede encontrar la diferencia aquí https://github.com/resin-io/docker/commit/9d155107b06c7f96a8951cbbc18287eeab8f60cc

@rhatdan @petrosagg ¿puedes crear un PR para esto?

@jeremyherbert el parche está en el demonio docker que viene en todas las versiones recientes de RHEL, CentOS y Fedora...

@graingert Lo hemos enviado en el pasado y ha sido rechazado.

@rhatdan , ¿tienes un enlace?

@runcom ¿Tienes el enlace?

@thaJeztah ¿ es esto algo que ustedes habrían rechazado?

Aquí hay una lista de problemas existentes que se han cerrado o a los que no se respondió:
https://github.com/docker/docker/issues/3949
https://github.com/docker/docker/issues/3156
https://github.com/docker/docker/issues/14251
https://github.com/docker/docker/issues/18603

Puede encontrar información sobre los parches de Project Atomic utilizados en RHEL/CentOS/Fedora en:
http://www.projectatomic.io/blog/2016/08/docker-patches/

@daveisfera parece que solo agregan volúmenes R, no volúmenes RW, por lo que no funcionará para @yngndrw y mi caso de uso.

@graingert ¿Por qué necesita volúmenes RW? Entiendo que solo lectura es una solución alternativa para ciertos casos.

Probar las migraciones de esquemas sería una buena razón...

El 01/11/2016 a las 10:36, Brian Goff escribió:

@graingert https://github.com/graingert ¿Por qué necesita volúmenes RW?
Entiendo que solo lectura es una solución alternativa para ciertos casos.


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

scott mcarty

scott [email protected]

http://crunchtools.com

@padrelinux

@ cpuguy83 Otro caso de uso para RW sería ccache

@fatherlinux No estoy seguro de seguir. ¿Por qué necesitarías un volumen para esto? Además, ¿por qué debe hacerse durante la fase de construcción?

Tengo un caso de uso ligeramente diferente para esta característica: paquetes de almacenamiento en caché que el administrador de paquetes ASP.Net 5 descarga/actualiza. El administrador de paquetes administra su propia carpeta de caché, por lo que, en última instancia, solo necesito una carpeta que pueda reutilizar entre compilaciones.

Ataría el montaje, por ejemplo:

docker build -v /home/jenkins/pythonapp/cache/pip:/root/.cache/pip  -t pythonapp .
docker build -v /home/jenkins/scalaapp/cache/ivy2:/root/.ivy2  -t scalaapp .

Porque hay muchas veces que la migración del esquema se tiene que hacer cuando
el software está instalado. Si ejecuta contenedores de solo lectura, debe
nunca instale software en ningún otro momento que no sea cuando esté en el
fase de construcción.....

El 01/11/2016 a las 10:42, Brian Goff escribió:

@fatherlinux https://github.com/fatherlinux No estoy seguro de seguir.
¿Por qué necesitarías un volumen para esto? Además, ¿por qué debe hacerse durante
la fase de construcción?


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/docker/docker/issues/14080#issuecomment-257583693 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAHLZfhBG8RUWtqPD-6RaLC7uoCNc-3nks5q50_TgaJpZM4FIdOc.

scott mcarty

scott [email protected]

http://crunchtools.com

@padrelinux

Sé que el contenido de estos directorios no hará que la compilación dependa del host (perder estos montajes hará que la compilación funcione de todos modos, solo que más lento)

NFS resolvió esto como hace 30 años...

El 01/11/2016 a las 10:45 a. m., Thomas Grainger escribió:

Sé que el contenido de estos directorios no detendrá la compilación
ser idempotente o dependiente del host (perder estos montajes causará
la construcción para trabajar de todos modos)


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

scott mcarty

scott [email protected]

http://crunchtools.com

@padrelinux

NFS resolvió esto como hace 30 años...

No es un comentario útil

@graingert lo siento, eso salió mal en serio. Estaba tratando de responder demasiado rápido y no di suficiente contexto. En serio, estamos considerando NFS en combinación con CRIO para resolver algunos de estos tipos de problemas.

Tanto el registro de imágenes como los bulbos tienen muchas cualidades en común. De lo que estás hablando es básicamente un problema de almacenamiento en caché. NFS, y en particular el almacenamiento en caché incorporado, puede hacer que las compilaciones sean independientes del host y manejen todo el almacenamiento en caché por usted.

Por lo tanto, incluso con una opción de tiempo de compilación -v, una compilación no tiene que estar bloqueada en un solo host. Puede que no sea independiente de la escala de Internet, pero es suficiente para muchas personas que controlan su entorno de construcción en un solo sitio o ubicación.

@fatherlinux Usaría gitlab o travis caching para tomar el directorio de caché y cargar/descargar en S3

@graingert sí, pero eso solo funciona en ciertos tipos de datos/aplicaciones, también solo en el nivel de depósito correcto, no en el nivel de metadatos y bloques de posix. Para ciertos tipos de aplicaciones front-end y middleware, no hay problema. Para una migración de esquema de base de datos, debe probar con anticipación y tener el caché local para la velocidad y, por lo general, debe ser posix.

Imagine que tengo un clúster de MySQL Galera con 1 TB de datos y quiero hacer una actualización y todos están en contenedores. La Galera fragmentada en contenedores/orquestada de múltiples nodos es realmente conveniente. No quiero tener que probar manualmente una migración de esquema durante cada actualización.

Quiero una instantánea del volumen de datos (pv en el mundo de Kube), exponerlo a un servidor de compilación, luego probar la actualización y la migración del esquema. Si todo funciona correctamente y las pruebas pasan, entonces construimos los contenedores de producción y dejamos que la migración del esquema ocurra en producción....

@graingert lo siento, olvidé agregar, luego descartar la instantánea que se usó en la ejecución de prueba... No quiero organizar un evento de compilación y prueba por separado, aunque eso sería posible...

@fatherlinux Creo que es un caso de uso ortogonal...

@graingert no es un comentario útil. ¿Ortogonal a qué? Ortogonal a la solicitud de -v durante la compilación, ¿de qué entendí que se trataba esta conversación?

Hay algunos usos diferentes que veo para esta bandera.

  • un caché, compartido entre los servidores de compilación docker
  • una palabra clave similar a ADD que solo se aplica 'durante la compilación' de un solo Dockerfile. Por ejemplo, AGREGAR un archivo enorme y luego excluirlo de las imágenes.
  • Una palabra clave similar a ADD+RUN que ignora toda la salida. Por ejemplo, AGREGAR un archivo enorme, luego EJECUTAR un paso e ignorar cualquier cambio en la imagen: AGREGAR+EJECUTAR en un paso y luego omitir una capa.

Los últimos dos casos de uso podrían resolverse de manera más limpia con dos nuevas palabras clave.

BUILDCONSTFILE <path>

Ejecutaría un COPY <path> antes de cada EJECUCIÓN y eliminaría <path> de la imagen después.

TEST <cmd> WITH <paths>

Lo que COPIARÍA las rutas, ejecutaría el comando, luego, con el estado de salida 0, continuaría la compilación desde la imagen principal; de lo contrario, detendría la compilación

Personalmente, creo que PRUEBA ... CON se maneja mejor en otro paso de CI que prueba su contenedor como un todo

Permítanme comenzar con esto: creo que estoy de acuerdo con agregar --mount para compilar ("-v" probablemente no tanto). No estoy 100% seguro de la implementación, cómo se maneja (o no se maneja) el almacenamiento en caché, etc.

Para el proyecto docker, lo que hacemos es construir una imagen de constructor.
Básicamente tiene todo lo que necesitamos, copia el código, pero en realidad no construye la ventana acoplable.
Tenemos un Makefile que organiza esto. Entonces make build construye la imagen, make binary construye el binario con build como dependencia, etc.

Hacer un binario ejecuta la imagen de compilación y hace la compilación, con esto podemos montar lo que necesitamos, incluidas las cachés de paquetes para compilaciones incrementales.
La mayor parte de esto es bastante sencillo y fácil de orquestar.
Por lo tanto, ciertamente hay formas de manejar este caso hoy, solo Docker por sí solo no puede manejar el 100% (y eso no es necesariamente algo malo) y tendrá que hacer que esto funcione con su sistema CI.

@ cpuguy83 Creo que esto resolvería la mayoría de mis casos de uso. Solo para que entienda, ¿quiere decir --montar para significar solo lectura? y -v para ser leído/escrito?

@ cpuguy83 también estamos construyendo principalmente imágenes "constructoras" que en mi humilde opinión se están convirtiendo en un patrón cada vez más común...

@fatherlinux swarm services y ahora (para 1.13) docker run admite --mount que es mucho más preciso y flexible: https://docs.docker.com/engine/reference/commandline/service_create/# /add -bind-montajes-o-volúmenes

Parece que a los documentos les falta el tercer tipo de montaje, tmpfs .

Ahh muy bueno, gracias...

El 01/11/2016 a las 14:20, Brian Goff escribió:

@fatherlinux https://github.com/fatherlinux servicios de enjambre y ahora
(para 1.13) |ejecutar ventana acoplable| soporta |--montar| que es mucho mas preciso
y flexible:
https://docs.docker.com/engine/reference/commandline/service_create/#/add -bind-mounts-or-volumes

Parece que a los documentos les falta el tercer tipo de montaje, |tmpfs|.


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

scott mcarty

scott [email protected]

http://crunchtools.com

@padrelinux

@cpuguy83 también usamos mucho el patrón de construcción y necesitamos un almacenamiento en caché que no persiste en la imagen y también sobrevive a la invalidación de la capa.

Construimos imágenes de Yocto y tenemos un caché de estado compartido en almacenamiento NFS. Otro caso de uso es el caché npm para que pueda invalidar toda la capa RUN npm install pero volver a calcularla más rápido debido a los paquetes almacenados en caché.

Como un posible compromiso basado en la publicación de @graingert , ¿no podría uno tener un hash opcional de su archivo enorme en el archivo acoplable, y luego la ventana acoplable verifica esto al ejecutar la compilación? Entonces no habría problemas con las compilaciones deterministas, y sería obvio para la persona que crea que no tiene las dependencias requeridas, en lugar de que simplemente explote con un error extraño en algún momento. Lo mismo ocurre con las claves ssh, etc., que de todos modos deberían distribuirse con el dockerfile.

También creo que cualquier idea que requiera _copiar_ el enorme archivo es menos que ideal. Los tamaños de archivo que estoy interesado en usar son del orden de 10 a 40 GB, e incluso con un buen SSD, eso vale al menos uno o dos minutos de copia. Este es mi problema con la directiva ADD que ya está en la ventana acoplable; No quiero AGREGAR 30 GB a mi imagen cada vez que se construye y tener que lidiar con tener todo ese espacio libre adicional, así como con la necesidad de aplastar imágenes.

Eso no funcionaría para lo que estamos usando. Tenemos un volumen que contiene cachés sstate del sistema de compilación yocto que está RW montado en enlace en la compilación porque cualquier pérdida de caché se calculará durante la compilación y se guardará en sstate para futuras. Nuestros directorios también tienen ~ 30 GB, por lo que incluso calcular el hash llevaría un tiempo.

Nunca entendí el concepto de construcción determinista. Hay maneras de pegarse un tiro en el pie incluso con la semántica actual. Por ejemplo, puede curl algo desde una IP interna. De repente, este Dockerfile no funciona en todas partes y depende del host. Pero hay casos legítimos de por qué querrías hacer eso. Por ejemplo, una caché HTTP local.

Entonces, dado que las compilaciones no son deterministas de todos modos, y dado que uno puede emular el volumen montado en enlace a través de la red hoy, ¿por qué no proporcionar una forma nativa de hacerlo con las advertencias apropiadas si es necesario?

@petrosagg @zrml @thaJeztah Lo que sabemos es:

  • Si azotamos a través de #7115 #3156 podemos encontrar una larga lista de temas que tienen muchos años discutiendo este mismo problema
  • La mayoría se cerraron por razones de reproducibilidad (o el antiguo comentario Dockerfile syntax is frozen , y luego de que se agregó la instrucción HEALTHCHECK , se eliminó la congelación pero los problemas permanecieron cerrados)
  • Este problema ha impedido que muchos equipos tengan una buena usabilidad/productividad de contenedores en el desarrollo diario durante muchos años. Como dijo @btrepp , esto es un infierno
  • La gente de Docker está al tanto de este problema, pero esto traería una clase de ¡Oh, mi compilación de docker se rompió! problemas debido al caché compartido que no es bueno
  • Pero pasar de la caché de disco a la caché de red no parece mejorar la confiabilidad de la compilación de ninguna manera, actúa simplemente como una caché sobre http glorificada, y se ha descubierto que empeora las cosas (descarga de Internet para cada compilación, HTTPS, tamaño de los archivos, disco duro al crear contenedores, almacenamiento en caché de capas, orquestación de compilación complicada, etc.)

Dado todo lo que sabemos, creo que esto probablemente se cerrará como Dupe o WontFix. No parece importar qué casos de uso damos. Actualización: estoy feliz de estar equivocado aquí. La propuesta parece abierta :)

Nuestra empresa pasó a un tiempo de ejecución de contenedor agnóstico y pronto tendrá que pasar también a una experiencia de creación de imágenes agnóstica. Pero este no será el lugar adecuado para discutir eso porque la negatividad no ayuda. Eso debería ser una publicación aparte.

@rdsubhas cuidado de compartir el enlace cuando haya terminado?

@rdsubhas es un buen resumen. No parece que este hilo se cerrará como dupe/wontfix ya que @cpuguy83 cree que está de acuerdo con agregar --mount durante la compilación que cubre la mayoría de los casos de uso.

Lo que me gustaría saber es que la propuesta actual:

  1. no altera la sintaxis de Dockerfile
  2. no hace que las compilaciones dependan más del host de lo que son actualmente

¿Cuáles son los contraargumentos que quedan con respecto a la idea? Si no hay ninguno, tal vez deberíamos comenzar a discutir los detalles de implementación para el mecanismo --mount .

Para reforzar el argumento de que las compilaciones ya dependen del host y no son reproducibles, proporciono una lista de fragmentos de Dockerfile con esta propiedad:

# Install different software depending on the kernel version of the host
RUN wget http://example.com/$(uname -r)/some_resource
# example.intranet is only accessible from specific hosts
RUN wget http://example.intranet/some_resource
# get something from localhost
RUN wget http://localhost/some_resource
# gcc will enable optimizations supported by the host's CPU
RUN gcc -march=native .....
# node:latest changes as time goes by
FROM node
# ubuntu package lists change as time goes by
RUN apt-get update
# install different software depending on the docker storage driver
RUN if [ $(mount | head -n 1 | awk '{print $5}') == "zfs" ]; then .....; fi

Honestamente, si solo agregamos --mount y dejamos que el usuario maneje la invalidación de caché ( --no-cache ), creo que estaremos bien. Es posible que deseemos ver un control de caché más detallado desde la CLI que todo o nada, pero ese es un tema aparte.

Mi caso de uso

He estado enfrentando un problema similar por un tiempo, pero opté por aumentar el tamaño de la imagen hasta que se finalice una solución. Intentaré describir mi escenario aquí en caso de que alguien encuentre una mejor solución.

Condiciones

  1. CircleCI tiene las claves ssh para descargar todas las dependencias internas durante la compilación
  2. GitHub aloja dependencias internas y otras se pueden descargar desde dentro de la imagen durante la compilación

Opciones

  1. Use --build-arg para pasar un token durante la compilación (totalmente desaconsejado). Esta es una opción muy atractiva y fácil ya que "simplemente funciona" sin ningún paso adicional.
  2. Descargue todas las dependencias y agréguelas al contexto de compilación. Desafortunadamente, ADD y COPY se ejecutan en capas separadas, por lo que me quedo con datos de capas anteriores.

El tamaño de algunas de mis imágenes se duplicó con creces en algunos casos, pero el tamaño total es tolerable por ahora. Creo que hubo un PR (parece que no puedo encontrarlo) para eliminar los argumentos de tiempo de compilación del historial de compilación, pero no fue aceptable debido a problemas de almacenamiento en caché irrc.
Estaré encantado de saber si se utilizan otras soluciones.

@misakwa es probable que admitamos secretos en la compilación 1.14.

Es muy emocionante escuchar a @cpuguy83. Estaré atenta a cuando se estrene. Definitivamente simplificará algunos de mis flujos de trabajo.

Es probable que admitamos secretos en la compilación 1.14.

¿Funcionará también para mapear el mapeo en tiempo de compilación de otro tipo de volúmenes como, por ejemplo yarn-cache ?

Por cierto, hay una forma interesante de crear imágenes de producción usando docker-compose, lo encontré funcionando y bastante efectivo:

Así que tienes un archivo de composición docker-compose.build.yml algo como esto:

services: 
  my-app:
    image: mhart/alpine-node:7.1.0
    container_name: my-app-build-container # to have fixed name
    volumes:
    - ${YARN_CACHE}:/root/.cache/yarn # attach yarn cache from host
    - ${HOME}/.ssh:/.ssh:ro    # attach secrets
    - ./:/source
    environment: # set any vars you need
     TEST_VAR: "some value"    
    ports:
    - "3000"
    working_dir: /app/my-app # set needed correct working dir even if if doesn't exist in container while build type
    command: sh /source/my-app.docker.build.sh # build script

1) construyes un contenedor usando docker compose:

$ docker-compose -f docker-compose.build.yml up --force-recreate my-app

crea un contenedor y ejecuta el script de compilación de shell my-app.docker.build.sh , no uso Dockerfile y hago todo en el script de compilación:

  • instalar los paquetes necesarios del sistema operativo
  • copie el código fuente necesario (de la carpeta asignada /source )
  • instalar dependencias
  • construir/compilar/probar si es necesario
  • elimine paquetes y cosas que no son necesarias para que funcione el entorno de destino (para reducir el tamaño de la imagen final)

Luego, crea una imagen desde el contenedor, reemplazando CMD porque eso debe ejecutarse en el entorno de destino:

docker commit -c "CMD npm run serve" my-app-build-container my-app-build-image:tag

Por lo tanto, su imagen está lista, utilizó caché de hilo externo y claves secretas externas que estaban disponibles solo durante el tiempo de compilación.

@whitecolor sí, eso funciona :) excepto por una cosa: docker build es realmente efectivo para cargar el contexto de compilación. Desafortunadamente, los volúmenes de origen montados no funcionan con demonios docker remotos (por ejemplo, docker-machine en la nube para computadoras portátiles de bajo consumo/ancho de banda). Para eso, tenemos que hacer una engorrosa serie de comandos acoplables docker run , docker cp , docker run , etc. y luego tomar una instantánea de la imagen final, pero es realmente complicado.

Realmente ayuda tener esto oficialmente como parte de la compilación de la ventana acoplable, y usar capas y contexto de compilación 😄

@rdsubhas Sí, tienes razón

@whitecolor Esa es una solución realmente simple y efectiva. Acabo de reducir una compilación de 30-40 minutos en un proyecto a unos 5 minutos. Espero con ansias la posibilidad de tener una función --mount on build, pero por ahora esta solución realmente desbloquea mi canalización.

Este es un comentario que dejé para el número 17745 que entendí que se había cerrado pero no se marcó como duplicado. Parece que me equivoqué en ese último punto: admito que estoy acostumbrado a sistemas como Bugzilla que marcan explícitamente algo como "DUPLICADO RESUELTO" y lo muestran en el área de descripción superior de un error. No soy un lector de mentes. (Así que mis disculpas @graingert , tenía pocas formas de saberlo, por lo tanto, no hay necesidad de gritarme en una fuente de 20 puntos, eso fue excesivo).


En mi caso, donde esto sería útil sería en los sistemas Debian: montando /var/cache/apt como un volumen, por lo que no vuelve a descargar los mismos archivos .deb una y otra vez. (La cuota de Internet verdaderamente "ilimitada" simplemente no existe, especialmente aquí en Australia, e incluso si existiera, se pierde tiempo esperando la descarga).

O en otro escenario, está haciendo una compilación, pero también genera informes de prueba, como listas de fallas e informes de cobertura de código que no necesita enviar con la imagen, pero que son artefactos útiles para tener a mano. Estos podrían escribirse en un volumen cuando un servidor de CI construye la imagen para que el servidor de CI los recoja y los aloje.

O esta noche, estoy haciendo algunas imágenes basadas en Gentoo para mí, me gustaría montar /usr/portage desde el host. No es difícil para un Dockerfile darse cuenta, "hey, /usr/portage (en el contenedor) está vacío, no hay problema, simplemente agarraré eso" cuando se ejecuta sin el volumen montado, O, simplemente usa el volumen tal como está, ahorrando tiempo al obtener una copia nueva.

Agregar esos conocimientos es una declaración if trivial en un script de shell Bourne... SI la lógica subyacente para montar el volumen está presente en primer lugar. En este momento, para mis imágenes de Gentoo, tengo que extraer /usr/portage cada vez que hago una compilación (afortunadamente, el espejo está en mi LAN), lo que significa que son unos buenos minutos de espera para que se complete ese paso.

Hay muchas razones por las que esta es una propuesta que vale la pena, y dudo que las compilaciones anidadas propuestas en #7115 ayuden en los casos anteriores.


@whitecolor tiene un enfoque interesante, pero si lo hago, también podría usar un Makefile completamente externo al sistema Docker para lograr la compilación.

@sjlongland No te estaba gritando, estaba llenando un gran aviso de "DUPLICADO RESUELTO"

Estoy usando docker y docker-compose para construir varios contenedores para nuestra infraestructura. Los contenedores son microservicios, en su mayoría escritos en nodeJS, pero hay un microservicio escrito en Java que utiliza el marco maven.
Cada vez que reconstruimos el contenedor de Java, se descargan decenas de dependencias de Maven; esto lleva varios minutos. Luego, el código se compila en aproximadamente 15 segundos.

Esto es muy feo y tiene un impacto muy fuerte en nuestra estrategia de CI.

En este escenario, realmente no importa si el volumen con las dependencias de compilación falta o está vacío, porque en ese caso se descargarían las dependencias. La reproducibilidad no se ve afectada.

Entiendo que hay problemas de seguridad, porque podría manipular las dependencias e inyectar un código desagradable allí; En mi humilde opinión, eso podría eludirse fácilmente al no permitir que las imágenes creadas con "volúmenes de compilación" se publiquen en docker-hub o docker-store.
Para explicar esto de otra manera, debe haber una distinción de alcances entre el uso empresarial y el uso personal de docker.

@stepps consulte https://pypi.python.org/pypi/shipwright en lugar de docker-compose

He estado siguiendo este hilo durante un tiempo, buscando una buena solución para mí. Para construir contenedores mínimos de manera flexible con un esfuerzo mínimo, me gusta mucho https://github.com/edannenberg/gentoo-bb de @edannenberg.

  • Separa las dependencias en tiempo de compilación de las dependencias en tiempo de ejecución.
  • Las compilaciones se realizan en contenedores y están aisladas, limpias y repetibles
  • Maneja las dependencias entre las imágenes y el orden de compilación

Se basa en el uso de portage y emerge de Gentoo, así que a @sjlongland le puede gustar para sus imágenes basadas en Gentoo. Los archivos dist y los paquetes binarios se almacenan en caché, por lo que no es necesario descargarlos ni compilarlos nuevamente, lo que hace que las reconstrucciones sean rápidas. Tiene ganchos para personalizar fácilmente el proceso de construcción. La instalación de software de terceros es fácil, como usar git para clonar un repositorio y luego compilarlo, conservando solo la compilación en la imagen final. Modela el Dockerfile.

Un ejemplo simple es para figlet es: -

construir.conf:

IMAGE_PARENT="gentoobb/glibc"

Dockerfile.plantilla:

FROM ${IMAGE_PARENT}
ADD rootfs.tar /
USER figlet
CMD ["gentoo-bb"]
ENTRYPOINT ["figlet"]

construir.sh

PACKAGES="app-misc/figlet"

configure_rootfs_build() {
        useradd figlet
}

Me gusta la solución de @whitecolor , es simple usar solo la tecnología Docker y luego un script de shell simple o cualquier otra cosa que desee usar. Estoy usando gentoo-bb porque es más completo. Shipwright se ve bien con características más enfocadas en el desarrollador, como el manejo de sucursales. https://github.com/grammarly/rocker también parece interesante. Gracias por compartir a todos.

Sólo otra voz añadida a la pila. Nuestro entorno de desarrollo muy complejo sería mucho más simple si pudiéramos montar volúmenes locales en la compilación.

Una solución es ejecutar durante una compilación un servidor http que exponga los archivos locales y luego usar curl/wget, etc. para obtener los archivos en la compilación de la ventana acoplable. Pero realmente desearía que esos trucos fueran innecesarios.

Otro caso de uso... Quiero crear imágenes acoplables para crear un sistema operativo propietario que tenga 10 versiones diferentes. El medio de instalación es > 80 GB, por lo que no puedo simplemente copiarlo en el entorno de compilación de la ventana acoplable. Un montaje de enlace sería mucho más preferible.

Otro: el uso de mi proyecto distribuye Dockerfiles en el repositorio para construir desde fuentes en el contenedor. Actualmente, extraemos otro clon de git en el contenedor de github. Hay clones superficiales y todo, pero aún así...

Entonces, acabo de probar [1] en un host de compilación rhel7, y la compilación de Red Hat del daemon docker SÍ tiene la opción -v para compilar. No he probado en CentOS/Fedora, pero uno podría imaginar que Fedora/CentOS probablemente también lo tenga. Vale la pena probar. Además, las suscripciones de RHEL Developer ahora son gratuitas [2]:

@fatherlinux Bajo Fedora `docker build -v' también está disponible.

@fatherlinux La versión CentOS 7 lo incluye.

+1 Creo que esta sería una característica realmente útil para agregar a la ventana acoplable oficial.

Acabo de actualizar tanto en centos como en linuxmint (ahora se ejecuta 17.03.1-ce), ¿me estoy perdiendo algo aquí? No puedo ver la opción -v

en menta

$ docker build --help

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --build-arg list             Set build-time variables (default [])
      --cache-from stringSlice     Images to consider as cache sources
      --cgroup-parent string       Optional parent cgroup for the container
      --compress                   Compress the build context using gzip
      --cpu-period int             Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int              Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int             CPU shares (relative weight)
      --cpuset-cpus string         CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string         MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust      Skip image verification (default true)
  -f, --file string                Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                   Always remove intermediate containers
      --help                       Print usage
      --isolation string           Container isolation technology
      --label list                 Set metadata for an image (default [])
  -m, --memory string              Memory limit
      --memory-swap string         Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --network string             Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                   Do not use cache when building the image
      --pull                       Always attempt to pull a newer version of the image
  -q, --quiet                      Suppress the build output and print image ID on success
      --rm                         Remove intermediate containers after a successful build (default true)
      --security-opt stringSlice   Security options
      --shm-size string            Size of /dev/shm, default value is 64MB
  -t, --tag list                   Name and optionally a tag in the 'name:tag' format (default [])
      --ulimit ulimit              Ulimit options (default [])
$ cat /etc/lsb-release 
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=18
DISTRIB_CODENAME=sarah
DISTRIB_DESCRIPTION="Linux Mint 18 Sarah"
$ docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Fri Mar 24 00:45:26 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Fri Mar 24 00:45:26 2017
 OS/Arch:      linux/amd64
 Experimental: false

en centos 7

# docker build --help

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --build-arg list             Set build-time variables (default [])
      --cache-from stringSlice     Images to consider as cache sources
      --cgroup-parent string       Optional parent cgroup for the container
      --compress                   Compress the build context using gzip
      --cpu-period int             Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int              Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int             CPU shares (relative weight)
      --cpuset-cpus string         CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string         MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust      Skip image verification (default true)
  -f, --file string                Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                   Always remove intermediate containers
      --help                       Print usage
      --isolation string           Container isolation technology
      --label list                 Set metadata for an image (default [])
  -m, --memory string              Memory limit
      --memory-swap string         Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --network string             Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                   Do not use cache when building the image
      --pull                       Always attempt to pull a newer version of the image
  -q, --quiet                      Suppress the build output and print image ID on success
      --rm                         Remove intermediate containers after a successful build (default true)
      --security-opt stringSlice   Security options
      --shm-size string            Size of /dev/shm, default value is 64MB
  -t, --tag list                   Name and optionally a tag in the 'name:tag' format (default [])
      --ulimit ulimit              Ulimit options (default [])
# docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Mon Mar 27 17:05:44 2017
 OS/Arch:      linux/amd64
# cat /etc/centos-release
CentOS Linux release 7.3.1611 (Core) 

@wilfriedroset En CentOS 7, los paquetes Docker no oficiales brindan la opción. Creo que es parte del repositorio de EPEL.

gracias @nathanjackson. ¿Tenemos una ETA para esta característica en el lanzamiento oficial?

@wilfriedroset AFAIK, NO HAY ETA porque se decidió (varias veces) que esta característica no DEBE estar en la ventana acoplable oficial para preservar la "portabilidad de compilación". también permite que sus Dockerfiles se ejecuten en cualquier lugar, incluido el servicio de compilación de Docker.

En mi experiencia, la portabilidad de construcción limitada es lo que los clientes realmente quieren. Quieren configurar un entorno/granja de compilación y se aseguran de que las compilaciones siempre se puedan reconstruir en ese entorno. La opción de compilación -v no evita esto de ninguna manera.

Por ejemplo, si usa montajes NFS, solo asegúrese de que todos los servidores de compilación tengan ese montaje en sus fstabs y su compilación se completará sin problemas en ninguna parte de la granja.

En RHEL 7.3
````
[ root@rhel7 ~]# docker compilación --ayuda

Uso: docker build [OPCIONES] RUTA | dirección URL | -

Cree una imagen a partir de un Dockerfile

Opciones:
--build-arg valor Establecer variables de tiempo de compilación (predeterminado [])
--cgroup-parent string Cgroup principal opcional para el contenedor
--cpu-period int Limita el período de CPU CFS (programador completamente justo)
--cpu-quota int Limite la cuota de CPU CFS (programador completamente justo)
-c, --cpu-shares int cuotas de CPU (peso relativo)
--cpuset-cpus string CPU en las que permitir la ejecución (0-3, 0,1)
--cpuset-mems cadena MEM en los que permitir la ejecución (0-3, 0,1)
--disable-content-trust Omitir verificación de imagen (verdadero predeterminado)
-f, --file string Nombre del Dockerfile (el valor predeterminado es 'PATH/Dockerfile')
--force-rm Quitar siempre los contenedores intermedios
--ayuda Uso de impresión
--isolation string Tecnología de aislamiento de contenedores
--label valor Establecer metadatos para una imagen (predeterminado [])
-m, --memoria cadena Límite de memoria
--memory-swap string Límite de intercambio igual a memoria más intercambio: '-1' para habilitar el intercambio ilimitado
--no-cache No use caché al construir la imagen
--pull Intentar siempre extraer una versión más nueva de la imagen
-q, --quiet Suprime la salida de compilación e imprime la identificación de la imagen si se realiza correctamente
--rm Eliminar contenedores intermedios después de una compilación exitosa (verdadero predeterminado)
--shm-size string Tamaño de /dev/shm, el valor predeterminado es 64 MB
-t, --tag value Nombre y, opcionalmente, una etiqueta en el formato ' nombre:etiqueta ' (predeterminado [])
--ulimit value Opciones de Ulimit (predeterminado [])
-v, --volume valor Establecer montajes de vinculación en tiempo de compilación (predeterminado [])
```

otro caso de uso en un proyecto de nodo de construcción de CI es compartir el caché yarn del CI al construir todas las imágenes.

+1: instalar node_modules una y otra vez es realmente terrible, especialmente para los microservicios de nodejs
Estoy tratando de resolver este problema con nfs, creo que "repetible" no es una buena razón para no implementar esta característica...

Esto parece que será aún más importante con #31257 y #32063 fusionados.

Echa un vistazo a #32507

@fatherlinux , ¿podría explicar cómo funciona la portabilidad de compilación cuando puede tener comandos COPY dentro del Dockerfile? Tengo un problema en el que quiero evitar la cantidad de copias de un archivo grande (por razones de complejidad de tiempo) y busco una opción de solo lectura en tiempo de compilación para compartir el archivo con el contenedor.

@arunmk @cpuguy83 exactamente. La idea es que realmente no desee COPIAR datos en el contenedor durante la compilación. Eso puede hacerlo muy grande. Solo queremos que los datos estén disponibles en el momento de la compilación. Según lo anterior, puede hacer un montaje de enlace -v en la versión de Red Hat del demonio docker que le permite tener datos disponibles, pero ahora solo se lee (me quemó la semana pasada).

Entonces, si lo necesita hoy, consulte Fedora, CentOS o RHEL y puede montar una copia de datos de solo lectura en el momento de la compilación...

Y, si necesita portabilidad dentro de una granja de compilación, sugeriría NFS o algo así...

Si no le importa copiarlo, sino solo tenerlo en la imagen final, puede usar compilaciones de varias etapas para manejar esto.

Un ejemplo inventado:

FROM fatImage AS build
COPY bigData /data
RUN some_stoff /data

FROM tinyImage
COPY --from=build /data/result

Gracias por la aclaración @fatherlinux
@ cpuguy83 gracias por el detalle. Permítanme agregar más detalles a mi problema, que puede ser poco común: tengo un sistema de compilación que genera un archivo de 3,3 GB. Eso se agrega a un RPM que se construye dentro de un contenedor docker. Por lo tanto, se producen dos copias: una desde el sistema de compilación en el contenedor de la ventana acoplable, una desde el contenedor de la ventana acoplable hasta el RPM. Ahora, no puedo evitar la segunda copia. Estaba pensando en evitar la primera copia, pero parece que tampoco es posible, incluso con las compilaciones de varias etapas.
Puedo entender que, si el archivo grande se usó repetidamente, la copia de múltiples etapas habría reducido la cantidad de veces que se ejecuta la copia a '1'. Lo uso una vez y quería reducir el número a '0'. ¿Tengo razón al entender que no será posible?

@arunmk No importa qué, tendrá que copiarse en la instancia de compilación desde el cliente.

@cpuguy83 gracias por la aclaración. Parece que tengo que tomar los gastos generales por ahora. ¿Es eso tener atomicidad?

@padrelinux

Intenté lo que dijiste, usando -v en RHEL7 para intentar montar un directorio de solo lectura durante la compilación, pero obtuve este error:

Los volúmenes no son compatibles con la compilación de Docker. Utilice solo soportes de enlace.

Esto solo funcionará con el paquete docker de RHEL, no con el de Docker. El parche no se aceptó en sentido ascendente.

@padrelinux

Intenté lo que dijiste, usando -v en RHEL7 para intentar montar un directorio de solo lectura durante la compilación, pero obtuve este error:

Los volúmenes no son compatibles con la compilación de Docker. Utilice solo soportes de enlace.

@fcntl

necesita usar enlaces como dice el error, probablemente usó -v /something en lugar de /hostsomething:/containersomething

@thebigb y quizás otros, hemos configurado una infraestructura para poder usar ccache durante las compilaciones de docker. lo hemos publicado en https://github.com/WebHare/ccache-memcached-server si te ayuda, aunque lo ideal sería que resolver este problema lo dejara obsoleto.

Estaba a punto de agregar, un caso de uso para el que realmente necesito esto es ccache. Me gustaría poder montar mi caché de ccache durante la creación de una imagen acoplable; no tiene sentido que esté en la imagen en sí. @unilynx Echaré un vistazo a tu solución: ¡buen momento!

Sólo otra voz.

Mi caso de uso: actualmente uso el comando MOUNT de rocker para compartir directorios /root/.cache y /var/cache/apk .

Por alguna razón, tengo un acceso de red muy (muy, muy) lento a los paquetes apk y pip. Cualquier reconstrucción hará que el proceso lleve mucho tiempo. Hace las cosas mucho más fáciles con esta función MOUNT en tiempo de compilación.

@embray @roxma eche un vistazo a https://github.com/moby/moby/issues/32507 si eso abordaría su caso de uso; comentarios bienvenidos

Con la introducción de compilaciones de varias etapas , creo que la necesidad de especificar un montaje de volumen para el caché local de Maven es crítica.

@ gim913 No es así como participas en ninguna comunidad. Si desea contribuir, revise las propuestas existentes vinculadas aquí para ver si alguna de ellas resuelve su caso de uso.

@ gim913 En esta etapa de la integración de la ventana acoplable en varias distribuciones, cambiar los entornos (es decir, eliminar la ventana acoplable por completo) parece mucho más disruptivo que cambiar su 'SO' (supongo que se refiere a cambiar de una distribución de Linux diferente a la compilación de RedHat que aparentemente incluye -v? )

¿No sería más fácil simplemente tomar la versión de ventana acoplable de RedHat? Tal vez alguien aquí pueda indicarle los parches/forks/commits relevantes para obtener la opción '-v' en la compilación.

@unilynx aquí tienes

Estaba mirando algunos ejemplos que usaban wget y llegué aquí... mi caso de uso es similar... Quiero descomprimir un tarball grande y simplemente ejecutarlo. No quiero ensuciar el archivo docker con el tarball o perder el tiempo haciendo un wget desde un servidor web local. Montar como puede hacer con docker compose parece algo razonable en el momento de la compilación. Combine el cambio de Puneeth si se ve bien :-)

Precompilo las ruedas de python y quiero instalarlas en el contenedor sin copiarlas y crear una capa que realmente no necesito, o que de alguna manera tengo que tratar de aplastar. Día 1 y ya estoy investigando rocker 😢 😢 😢

Esto sería fácil de agregar y extremadamente útil (o un comando de montaje, vea rocker nuevamente). ¿Cuánto tiempo se dedica (en la comunidad) a generar secuencias de comandos en torno a esta u otras características faltantes similares?

@awbacker Multi-stag build resuelve esto bastante bien donde puedes hacer algo como

FROM something AS my_wheels
RUN compile_all_the_things

FROM something
COPY --from my_wheels /wherever
RUN do_stuff_with_wheels

La primera parte solo se ejecuta si algo cambia. El caché para él también se puede compartir entre otras compilaciones/dockerfiles.
Esto hace que toda la construcción sea autónoma.

También hay una propuesta que permitiría RUN --mount donde la especificación de montaje le indicaría que monte algo desde el objetivo de compilación my_wheels en lugar de copiarlo.

Al igual que para @kenyee , esto podría montar algo del contexto de compilación, que en 17.07-experimental solo se envía de forma incremental según sea necesario.

@ cpuguy83 Eso no funciona en la práctica, al menos para las compilaciones Gradle Java. Tengo una imagen base de Docker que tiene los archivos de Gradle Jar almacenados previamente en caché, pero la compilación de Gradle de su fuente es lo que desencadena la descarga de todas sus dependencias en el caché.

@ cpuguy83 multi-stage no permite eliminar las ruedas copiadas de la imagen resultante, es de lo que habla @awbacker . Por lo tanto, el contenido de la carpeta /wherever se almacenará en caché y se aumentará el tamaño de la imagen.

@BryanHunt Entonces, ¿parte de su proceso de compilación es descargar las dependencias? ¿Seguro que Gradle debe proporcionar una forma de almacenarlos en caché sin pasar por ellos y construirlos realmente?

@cpuguy83 Sí, las dependencias se descargan como parte de la compilación. Básicamente lo mismo que Maven. Para referencia: https://github.com/gradle/gradle/issues/1049

¿Había un PR para montajes de construcción en alguna parte?

@graingert Aquí

👍 por esto. En Lunar Way, queremos realizar el proceso completo de "compilación -> prueba -> compilación de imagen de producción" en una sola compilación de Docker para eliminar las dependencias de compilación y prueba del servidor de CI. Con compilaciones de varias etapas podemos hacer esto, pero no podemos obtener los resultados de la prueba del contenedor intermedio en el proceso de compilación. Por lo tanto, tenemos que hacerlo en dos pasos en este momento: con un Dockerfile separado para crear la imagen de prueba, ejecutarlo y luego continuar con el paso de creación de la imagen de producción, si las pruebas tienen éxito.

Una opción -v en la compilación de la ventana acoplable nos permitiría almacenar los resultados de la prueba en una carpeta montada desde el servidor de CI y eliminaría la necesidad del proceso actual de 2 pasos.

@tbflw De forma predeterminada, la compilación de Docker no elimina los contenedores intermedios después de una compilación fallida. Entonces, si una prueba falla, puede obtener los resultados de la prueba.

Por favor , ¡realmente también necesitamos esta función! Recurrir a otras herramientas como rocker o forking docker con parches ad-hoc es mucho más feo que romper la noción evangélica de "portabilidad de compilación".

@BryanHunt @stepps @yngndrw otros también @awhitford
Una forma de almacenar en caché las dependencias de compilación es hacer que su compilación funcione como el ejemplo de compilación de varias etapas en la documentación o el Dockerfile de python onbuild .
Aquí hay un ejemplo que hice que parece funcionar para maven. Lo copiaré aquí.

FROM maven
WORKDIR /usr/src/app
# /root/.m2 is a volume :(
ENV MAVEN_OPTS=-Dmaven.repo.local=../m2repo/
COPY pom.xml .
# v2.8 doesn't work :(
RUN mvn -B -e -C -T 1C org.apache.maven.plugins:maven-dependency-plugin:3.0.2:go-offline
COPY . .
RUN mvn -B -e -o -T 1C verify

FROM openjdk
COPY --from=0 /usr/src/app/target/*.jar ./

Debe configurarse para que descargue las dependencias antes de copiar el resto del código base. También asegúrese de que el lugar donde se almacenan sus artefactos no esté en un VOLUMEN .

@sixcorners Eso no funciona para Gradle

@BryanHunt ¿ Este Dockerfile o este enfoque no funcionan para gradle? cpuguy83 preguntó si había alguna forma de descargar dependencias sin realizar una compilación. Se vinculó a una tarea de resolución de dependencias. ¿No podría simplemente agregar el archivo build.gradle y ejecutar esa tarea?

@sixcorners Cuando tiene muchos módulos, debe replicar su estructura de directorios junto con los archivos de compilación y los archivos de propiedades. Supongo que podría hacerse, pero veo que esto es muy propenso a errores.

El multietapa de @sixcorners es un truco interesante y lo he visto utilizado para diferentes administradores de paquetes (por ejemplo, npm, composer).

Sin embargo, hay un problema, cada vez que se cambia la lista de dependencias COPY pom.xml en la imagen de la etapa 0, la capa se elimina y, por lo tanto, desaparece todo el caché. Eso significaba que cada vez que un desarrollador cambia algo en el pom (un comentario, una dependencia de 1kBytes), todo el caché debe volver a descargarse.

Para las máquinas de CI que construyen la imagen y luego ejecutan las pruebas con dependencias que siguen cambiando, son miles y miles de paquetes que deben volver a descargarse (ya sea desde un proxy o desde arriba) y hacen que la reconstrucción sea bastante lenta. Un caché basado en archivos locales montado como un volumen es mucho más rápido.

Ese también es un problema cuando los desarrolladores iteran la construcción de una imagen, especialmente si tienen conexiones lentas. Aunque uno puede configurar una instancia local de Nexus y http_proxy, pero eso tiene otros efectos secundarios (como canalizar cualquier solicitud de http a través de Nexus).

Multietapa es una buena solución, pero no es ideal.

Una solución que estamos a punto de probar es construir una imagen construyendo nuestras bibliotecas compartidas y reteniendo el caché de dependencia. Esta imagen se convertiría en nuestra imagen de compilación para nuestras aplicaciones. No es ideal, pero creemos que vale la pena intentarlo.

Sin embargo, hay un problema, cada vez que se cambia la lista de dependencias, COPY pom.xml en la imagen de la etapa 0 hace que la capa se elimine y, por lo tanto, todo el caché desaparece. Eso significaba que cada vez que un desarrollador cambia algo en el pom (un comentario, una dependencia de 1kBytes), todo el caché debe volver a descargarse.

@hashar tenga en cuenta que la función COPY --from no se limita a las etapas de construcción; de la referencia de Dockerfile :

Opcionalmente COPY acepta un indicador --from=<name|index> que se puede usar para establecer la ubicación de origen en una etapa de compilación anterior (creada con FROM .. AS <name> ) que se usará en lugar de enviar un contexto de compilación por el usuario La bandera también acepta un índice numérico asignado para todas las etapas de compilación anteriores que comenzaron con la instrucción FROM . _ En caso de que no se pueda encontrar una etapa de compilación con un nombre específico, se intenta usar una imagen con el mismo nombre en su lugar. _

Esto le permite _construir_ una imagen para sus dependencias, etiquetarla y usarla para copiar sus dependencias. Por ejemplo:

FROM maven
WORKDIR /usr/src/app
# /root/.m2 is a volume :(
ENV MAVEN_OPTS=-Dmaven.repo.local=../m2repo/
COPY pom.xml .
# v2.8 doesn't work :(
RUN mvn -B -e -C -T 1C org.apache.maven.plugins:maven-dependency-plugin:3.0.2:go-offline
COPY . .
RUN mvn -B -e -o -T 1C verify
docker build -t dependencies:1.0.0 .

Y especifica usando la imagen dependencies:1.0.0 para tus dependencias;

FROM openjdk
COPY --from=dependencies:1.0.0 /usr/src/app/target/*.jar ./

O (solo un ejemplo muy básico para probar);

$ mkdir example && cd example
$ touch dep-one.jar dep-two.jar dep-three.jar

$ docker build -t dependencies:1.0.0 . -f -<<'EOF'
FROM scratch
COPY . /usr/src/app/target/
EOF

$ docker build -t myimage -<<'EOF'
FROM busybox
RUN mkdir /foo
COPY --from=dependencies:1.0.0 /usr/src/app/target/*.jar /foo/
RUN ls -la /foo/
EOF

En el resultado de la compilación, verás:

Step 4/4 : RUN ls -la /foo/
 ---> Running in 012a8dbef91d
total 8
drwxr-xr-x    1 root     root          4096 Oct  7 13:27 .
drwxr-xr-x    1 root     root          4096 Oct  7 13:27 ..
-rw-r--r--    1 root     root             0 Oct  7 13:26 dep-one.jar
-rw-r--r--    1 root     root             0 Oct  7 13:26 dep-three.jar
-rw-r--r--    1 root     root             0 Oct  7 13:26 dep-two.jar
 ---> 71fc7f4b8802

No sé si alguien ha mencionado este caso de uso todavía (busqué brevemente en la página), pero montar un socket de autenticación SSH en el contenedor de compilación facilitaría mucho la utilización de dependencias que se implementaron a través de repositorios privados de git. Habría menos necesidad de repetitivo dentro del Dockerfile con respecto a la copia de claves en etapas de construcción no finales, etc.

buildkit tiene soporte nativo para git
https://github.com/moby/buildkit

Resolviendo.
Cree un script bash (~/bin/docker-compose o similar):

#!/bin/bash

trap 'kill $(jobs -p)' EXIT
socat TCP-LISTEN:56789,reuseaddr,fork UNIX-CLIENT:${SSH_AUTH_SOCK} &

/usr/bin/docker-compose $@

Y en Dockerfile usando socat:

...
ENV SSH_AUTH_SOCK /tmp/auth.sock
...
  && apk add --no-cache socat openssh \
  && /bin/sh -c "socat -v UNIX-LISTEN:${SSH_AUTH_SOCK},unlink-early,mode=777,fork TCP:172.22.1.11:56789 &> /dev/null &" \
  && bundle install \
...
or any other ssh commands will works

Luego ejecuta docker-compose build

Para tirar otro caso de uso en la pila. Uso Docker para Windows para generar un sistema de archivos para construir un sistema Linux integrado en un contenedor y me gustaría compartirlo con otros contenedores durante su paso de construcción. Interactué con este contenedor cambiando la configuración y reconstruyendo, etc., por lo que realizar la compilación en un Dockerfile y usar compilaciones de varias etapas no es una buena opción, ya que perdería compilaciones incrementales. Quiero almacenar en caché mis artefactos de compilación anteriores, ya que se tarda aproximadamente 1,5 horas en realizar una compilación limpia. Debido a la forma en que Windows trata con los enlaces simbólicos, no puedo hacer mi compilación en un volumen montado en el host, por lo que uso volúmenes con nombre. Idealmente, me gustaría compartir estos volúmenes con nombre en los pasos de construcción de mis otras imágenes; ya que en este momento tengo que crear un tar de la salida de compilación (alrededor de 4 gb) y luego hacer una copia de la ventana acoplable para que esté disponible en el host de Windows para compilaciones posteriores.

En el caso de python, cuando pip install package , él y sus dependencias se descargan en una carpeta de caché y luego se instalan en los paquetes del sitio.
Como buena práctica, usamos pip --no-cache-dir install package para no almacenar basura/caché en la capa actual. Pero para una mejor práctica, se desea poner la carpeta de caché fuera del contexto de compilación. así que build time -v ayudará.
algunos usuarios mencionados anteriormente para usar COPY . /somewhere/in/container/ está bien para la aplicación o los archivos del usuario, pero no para el caché. porque COPY crea una capa más como propia y eliminar cachés en capas posteriores no será útil. Otro efecto secundario negativo es que si el caché cambia cuando usamos COPY, el contexto cambia y las siguientes capas se invalidarán y se verán obligadas a reconstruir.

@wtayyeb Si tiene Dockerfile que ejecuta pip install ... solo cuando cambia el archivo de requisitos, entonces el tiempo de compilación -v no parece tan importante ya que los requisitos no cambian tan a menudo como las aplicaciones cuando se compilan.

@wtayyeb Puede usar Dockerfile de varias etapas para tener tanto el caché como una imagen ajustada. Es decir, use una imagen de instalación para instalar python en algún directorio y luego, para su imagen final, use COPY --from para transferir solo los archivos de python necesarios sin ningún artefacto de instalación o incluso pip.

@manishtomar , ¡Gracias, sí y no! En caso limpio, todas las dependencias se descargan nuevamente y se compilan y convierten en ruedas y se almacenan en caché, luego se instalan en el entorno de destino. Entonces, si uno pone requisitos allí, es un trabajo de una sola vez. Pero si se actualiza una pequeña dependencia, todas las dependencias deben volver a descargarse, reconstruirse, volver a rodar y volver a almacenar en caché para que sean utilizables.
Cuando use un CI para construir y probar sus bibliotecas y sus aplicaciones en una matriz de varios trabajos, multiplique el trabajo anterior en la cantidad de trabajos simultáneos en su servidor CI y obtendrá un aumento de iowait a más de 3 segundos y un promedio de carga superior a 15 incluso con SSD. (estos números son reales para 2 compilaciones simultáneas y aplicaciones con ~20 dependencias) Creo que pip cache lo está haciendo de la manera correcta, evitando volver a descargar, reconstruir y volver a enviar los paquetes listos. y sin bind -v perdemos tiempo y recursos del servidor.

@ibukanov , Gracias. Estoy usando Dockerfile de varias etapas para crear mis paquetes de aplicaciones y usarlos más tarde. Sería útil si solo tengo un Dockerfile y quiero compilarlo varias veces, pero ¿qué pasa si hay varios Dockerfiles y cada uno está compilado en una versión de Python (2.7, 3.6 por ahora) y también tiene varias extensiones C que necesitan ser construido para la imagen base seleccionada? ¿Qué pasa con el párrafo anterior?

@thaJeztah Su sugerencia es excelente y nos ahorrará algo de tiempo, sin embargo, en el caso de los cachés de compilación, realmente no queremos tener que copiar nada de la otra imagen.
¿Por qué no podemos acceder a otra imagen sin copiarla?

@thedrow mi ejemplo fue con las características que están actualmente allí; eche un vistazo a la propuesta RUN --mount (https://github.com/moby/moby/issues/32507), que puede ser más adecuada para su caso de uso

Al leer el hilo anterior, veo una gran cantidad de personas que intentan encontrar errores para corregir una brecha de funcionalidad básica en el proceso de compilación de la ventana acoplable. No veo argumentos convincentes sobre la base de la portabilidad sin combinar necesariamente los montajes de host con los montajes de imágenes, argumentos que son francamente engañosos y perezosos.

También soy un usuario de contenedores de Gentoo y fui redirigido desde https://github.com/moby/moby/issues/3156 , que es un caso de uso completamente válido para esta funcionalidad faltante.

Todo lo que realmente quiero es la capacidad de montar el contenido de otra imagen en el momento de la compilación para no inflar mis imágenes.

@kbaegis suena como una coincidencia exacta con la característica que se propone en https://github.com/moby/moby/issues/32507

Por supuesto. Ese solo ha sido un P3 no implementado en la cartera de pedidos durante un año en lugar de 3 años.

Parece que https://github.com/projectatomic/buildah en realidad va a superar la compilación de docker bastante rápido aquí para esta funcionalidad básica. Creo que voy a cambiar mi tubería una vez que eso suceda.

@kbaegis , ¿qué vino a agregar aquí a esta discusión? Usted describió un caso de uso que _exactamente_ coincide con una propuesta diferente;

Todo lo que realmente quiero es la capacidad de montar el contenido de otra imagen en el momento de la compilación para no inflar mis imágenes.

Es de código abierto, las cosas no surgen mágicamente.

¿Qué estoy buscando para agregar a la discusión?

Sucintamente, me estoy alejando de este conjunto de herramientas. Estoy seguro de que es información valiosa para el equipo de desarrollo, ya que estoy seguro de que no estoy solo allí.

La velocidad glacial y la baja prioridad para admitir este caso de uso (y cualquier solución alternativa confiable que proporcione esta funcionalidad) me ha obligado a usar otras herramientas y estoy abandonando esta canalización de compilación debido a la falta de funcionalidad.

Tengo un caso de uso (repetición, estoy seguro) para agregar. #32507 puede adaptarse mejor a esto.

Estoy creando una imagen acoplable para algunas canalizaciones bioinformáticas. Algunas de las herramientas requieren que algunas bases de datos estén presentes antes de su compilación/instalación (no preguntes, no es mi código ). Estas bases de datos pesan un encantador mínimo de 30 gb.

Durante el tiempo de ejecución, ciertamente tengo la intención de que esas bases de datos se monten en volúmenes -v . Desafortunadamente, no puedo hacer esto durante el proceso de construcción sin "hornearlos", lo que da como resultado una imagen de tamaño bastante obsceno.

@draeath echa un vistazo a https://github.com/grammarly/rocker . Ya es compatible con una hermosa instrucción MOUNT.

@draeath también, echa un vistazo a Buildah, admite montajes de forma predeterminada porque está configurado más como una herramienta de programación. También admite montajes con un Dockerfile:

https://github.com/projectatomic/buildah

Gracias @fatherlinux y @lig - esto me ayudará a realizar mi tarea. Sin embargo, sigo pensando que no debería tener que desviarme del proyecto para hacerlo, y aún me encantaría ver esto y #32507 implementados;)

He venido aquí a través de algunas búsquedas en Google para solicitar la misma función, volúmenes en el momento de 'construcción de la ventana acoplable', no en el tiempo de 'ejecución de la ventana acoplable'.

Tenemos un sistema embebido que contiene una CPU. El fabricante proporciona herramientas para componer una imagen del sistema y luego transferir la imagen a la CPU. Esta herramienta es de terceros para mí y no puedo cambiarla. Es poco probable que el fabricante lo modifique a petición mía.

Quiero crear una imagen de la ventana acoplable que haga un primer paso "construya la imagen del firmware" y luego pueda generar contenedores que simplemente empujen la imagen del firmware a las PCB recién salidas de la línea. Un Dockerfile podría verse así:
----------[ Corta aquí ]----------
DESDE la imagen base como constructor
COPIAR origen origen
EJECUTAR build-src

DESDE la imagen base como flasher
COPY --from=construir artefactos del constructor
EJECUTE cpu-build-and-flash --build-only
----------[ Corta aquí ]----------
Desafortunadamente, el paso de compilación y flasheo de la CPU requiere acceso al dispositivo de destino a través del bus USB, aunque no va a enviar la imagen del firmware al dispositivo. Por lo tanto, necesito tomar el '-v /dev/usb/bus:/dev/usb/bus' del comando 'docker run' y tenerlo en la compilación.

Está claro que esto no es posible actualmente.

La solución alternativa que voy a seguir es crear manualmente una imagen parpadeante mediante el 'contenedor acoplable' asignando un contenedor a una imagen. Preferiría simplemente montar el bus USB en el momento de la compilación.

Actualización para cualquiera que esté interesado: recientemente reconstruí mi tubería completa con éxito con buildah. Actualmente tengo las dos canalizaciones de compilación ejecutándose en paralelo y la canalización oci/buildah está generando imágenes más pequeñas (eliminando específicamente /usr/portage en mi caso al enmascararlo con otro montaje).

Y finalmente esta función está aquí: https://github.com/docker/docker-py/issues/1498

Pero quiero volúmenes RW para un caché de compilación

El sábado 28 de abril de 2018 a las 17:29 Коренберг Марк, [email protected] escribió:

Y finalmente esta característica está aquí: docker/docker-py#1498
https://github.com/docker/docker-py/issues/1498


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

También me gustaría ver esta característica (con capacidades de escritura) para que un archivo de resultados de prueba de unidad se pueda exportar durante el proceso de compilación de varias etapas en una canalización de CI. Para mantener el espíritu de la portabilidad de compilación, si no se proporcionó el interruptor -v, el archivo simplemente se escribiría internamente dentro de la imagen de prueba en esa etapa.

El objetivo ideal es compilar una vez, probar una vez y aún tener el archivo de resultados en el sistema host, incluso en el caso (y especialmente en el caso) de que las pruebas fallen y se detenga la compilación.

Sí por favor. Todo el dia.

No es del todo relevante, pero estamos migrando una parte de nuestra infraestructura de implementación y necesitábamos una forma de copiar archivos de una imagen después de la compilación. Lo siguiente hizo el truco:

docker build -t x .
ID=$(docker create x)
docker cp $ID:/package.deb .
docker rm $ID

Ya debería haberse agregado cuando se introdujo el archivo docker multietapa. Eventualmente, todos enfrentarán este problema tan pronto como comiencen a ejecutar pruebas unitarias como una etapa en un archivo docker de varias etapas, especialmente en el caso de canalizaciones de compilación de CI. También nos enfrentamos a este problema en el que tenemos que publicar informes de pruebas unitarias en VSTS. Ya estoy aplicando la solución alternativa que ha mencionado @hoffa . Pero después de todo, es una solución y complica las cosas.

¿Deberíamos hacer un problema diferente para las personas que quieren/necesitan volúmenes de tiempo de compilación para un caché de compilación?

@ajbouh Sí, probablemente en https://github.com/moby/buildkit/issues

Consulte https://github.com/moby/moby/issues/32507#issuecomment -391685221

El miércoles 23 de mayo de 2018 a las 19:22, Akihiro Suda [email protected] escribió:

@ajbouh https://github.com/ajbouh Sí, probablemente en
https://github.com/moby/buildkit/issues


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

Si bien no puede agregar volúmenes en el momento de la compilación, puede agregar hosts, por lo que ahora construyo todas mis imágenes de la ventana acoplable con algo como --add-host yum-mirror:$MIRROR_IP que sirve un espejo yum que mis imágenes de compilación luego detectan a través de un envoltorio alrededor mmm Útil cuando mi proyecto cambia de dependencia muchas veces al día y estoy desconectado o con una mala conexión (parte del proyecto implica actualizar y limpiar sus muchas dependencias).

Encuentro exasperante la resistencia de Docker a resolver este problema.

Recientemente se fusionó el soporte experimental para buildkit, que viene con una opción para RUN --mount=<opts> <command> .

enlace a la nota de @ cpuguy83 : https://github.com/moby/buildkit/pull/442

@glensc @cpuguy83 ¿ Cuándo podemos esperar un lanzamiento para esta función fusionada?

+1

RUN --mount no tiene soporte de volumen, por lo que cosas como https://github.com/avsm/docker-ssh-agent-forward siguen siendo imposibles en el momento de la compilación, ¿cuál es la solución para esto?

docker build --secret finalmente está disponible en Docker 18.09 https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

¿Podemos cerrar este tema?

--secret no se puede usar para el caso de uso de almacenamiento en caché, por lo que puedo decir.

@AkihiroSuda RUN --mount en general parece algo que posiblemente se ajuste como solución para este problema.

Sí, supongo que RUN --mount=type=cache (para volumen de caché) y --mount=type=secret con docker build --secret (para volumen secreto) casi cubre el problema.

@AkihiroSuda entonces, sería bueno ver un ejemplo de trabajo que resuelva el problema original

@AkihiroSuda Del artículo (https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066) Vi 2 casos de uso de montaje durante la compilación: secreto y SSH

[Secreto]

docker build --secret id=mysite.key,src=path/to/mysite.key .
RUN --mount=type=secret,id=mysite.key,required <command-to-run>

[SSH]

RUN --mount=type=ssh git clone [email protected]:myorg/myproject.git myproject

Hay otros 2 casos de uso (que recuerdo) que no se explican cómo usarlos en el artículo ni en este número:

1) [Caché] RUN --mount=type=cache
2) Volúmenes en general (por ejemplo, para montar certificados SSL, o en el caso de grandes volúmenes que deban usarse durante la construcción, pero no incluidos en la imagen generada, etc.)

Una vez que el caso de uso está montando el espacio de trabajo yarn antes de ejecutar webpack

Puedes hacer todo esto..

RUN --mount=type=cache,from=<some image>,source=<path in from image>,target=<target>

También puede reemplazar from=<some image> a from=<some build stage>

Aquí hay un ejemplo artificial:

# syntax=docker/dockerfile:1.0.0-experimental
FROM busybox as hello
RUN  echo hello > /hello.txt

FROM scratch
RUN --mount=type=cache,from=busybox,source=/bin,target=/bin --mount=type=cache,from=hello,source=/hello.txt,target=/tmp/hello.txt echo /tmp/hello.txt

Estoy de acuerdo con @AkihiroSuda , esto debería manejar todos los casos... pero háganos saber si no es así.

@AkihiroSuda @cpuguy83 : Desafortunadamente, la implementación actual (buildkit en docker 18.09) tiene problemas con los registros privados. A partir de ahora, estas nuevas funciones no se pueden usar si tiene que obtener sus imágenes a través de un registro privado. Vea mis pruebas en https://github.com/moby/moby/issues/38303.

Creo que esto también se usaría para los artefactos de Jenkins, así que, por ejemplo, si estoy creando una imagen de Docker y compilando algo dentro, quiero obtener algunos artefactos como, por ejemplo, la salida de junit pytest

Esto sería muy útil. Realmente preferiría no tener que agregar --experimental para admitir RUN --mount=type=cache /user/.cache/pip pip install (para ahorrar toneladas de ancho de banda de índice de paquetes).

buildah bud ( buildah build-using-dockerfile ) tiene una opción --volume / -v :
https://github.com/containers/buildah/blob/master/docs/buildah-bud.md

buildah puede ejecutar compilaciones como no root sin un conector acoplable.

¿Porque las descargas de paquetes desde la red son más reproducibles?

No es necesario agregar "--experimental", solo "DOCKER_BUILDKIT=1" en el cliente.

Sí, las compilaciones de red son más reproducibles en el sentido de que todo el contexto está en el Dockerfile. Si tiene que montar el contexto desde el host para que la compilación funcione, es una mala experiencia.

Tenga en cuenta que también puede montar una imagen en el archivo build.

Sí, las compilaciones de red son más reproducibles en el sentido de que todo el contexto está en el Dockerfile.

Seguramente tener RUN apt-get update en el Dockerfile asegura que uno tiene todos los pasos necesarios para construir la imagen. Sin embargo, no es reproducible ya que se descarga contexto adicional de un tercero. La única diferencia con un montaje es que todos los contextos externos están definidos en el Dockerfile.

Si tiene que montar el contexto desde el host para que la compilación funcione, es una mala experiencia.

Mi mala experiencia con la compilación de Docker es que nunca es reproducible y definitivamente podríamos beneficiarnos al montar un caché desde el host, lo que posiblemente aceleraría algunos casos de uso.

Lo que termino haciendo eventualmente es tener una compilación de varias etapas. Una imagen que obtiene el contexto de la red, que actúa como una instantánea del contexto remoto. Luego etiquete eso con alguna versión arbitraria, la fecha funciona bien. P.ej:

RUN apt-get update

docker build -t aptupdate-20190417

Y en la imagen real:

FROM aptupdate-20190417
FROM somebaseimage

COPY --from=aptupdate-20190417 /var/apt /var/apt

Repita con otro contexto remoto y más o menos tiene algo que es reproducible.

O en resumen: un Dockerfile que se basa en el acceso a la red probablemente no sea reproducible. Un montaje podría hacer que no sea reproducible, pero ayudaría a que algunos casos de uso fueran reproducibles. Pero supongo que el punto es que Dockerfile debería tener todos los pasos necesarios para construir la imagen, aunque en mi experiencia, la mayoría escribe sus propias herramientas para crear imágenes de instrumentos.

Quiero decir, RUN --mount=type=cache es exactamente para esto.
O incluso puede montar desde otra imagen de un registro y se recuperará.

Sus comandos apt se pueden hacer (relativamente) reproducibles fijando lo que desea obtener.
Pero si realmente quiere controlar todos los bits, ¿por qué está usando apt en su compilación? Almacenar esto en un host de compilación no es reproducible y se rompe fácilmente de un host a otro.
Mantenerlo en un registro no es malo, aparte de la posibilidad de que falle la red... lo cual, por supuesto, es una crítica justa.

-v en buildah y la bifurcación de redhat se rechazó explícitamente aquí porque es demasiado amplio... por no decir que no es útil, pero se rompe fácilmente de un host a otro, lo que va en contra del diseño de docker build .
Mientras tanto, la razón por la que RH lo agregó (o, más precisamente, por la que decidieron trabajar en él) fue para poder montar las credenciales de RHEL en el entorno de compilación.

Sí, las compilaciones de red son más reproducibles en el sentido de que todo el contexto está en el Dockerfile. Si tiene que montar el contexto desde el host para que la compilación funcione, es una mala experiencia.

Estoy vehementemente en desacuerdo. La red puede estar caída o comprometida; en cuyo caso, un caché local evita que toda la compilación falle mientras Internet no funciona.

Podría especificar volumes: una vez en mi docker-compose.yml; pero en su lugar necesita hacer DOCKER_BUILDKIT=1 y agregar RUN --mount=type=cache en Dockerfiles administrados aguas arriba? ¿Por qué?

Con las compilaciones de CI, estamos hablando de una cantidad no trivial de descargas innecesarias de decenas a miles de paquetes (decenas o cientos de veces al día) que podrían almacenarse en caché en un montaje de volumen (en una compilación que se ejecuta como no root sin la capacidad de ejecutar contenedores privilegiados con sus propios volúmenes en el host).

Los índices de paquetes son en muchos casos generosamente apoyados por donaciones. Desperdiciar ese dinero en ancho de banda para satisfacer una falsa idea de reproducibilidad basada en la falsa creencia de que los recursos remotos son un caché más reproducible de componentes de construcción es terriblemente frustrante.

Simplemente agregue --volume para que mi docker-compose.yml funcione.

Simplemente agregue --volume para que mi docker-compose.yml funcione.

Hacer que su "docker-compose" simplemente funcione es al revés.
docker-compose consumidores este proyecto, no al revés.

docker-compose interactúa con el socket de la ventana acoplable. docker-compose YAML es una forma consolidada de almacenar opciones de contenedores (que se pueden convertir a definiciones de pod de k8s (que podman admite, hasta cierto punto)). ¿Cómo debo especificar DOCKER_BUILDKIT=1 de forma reproducible? Podría especificar build_volumes: de forma reproducible en un docker-compose.yml.

Cuando, en mi secuencia de comandos de compilación de CI que se ejecuta n veces al día, construyo una imagen, por ejemplo, llamando a docker-compose build (por ejemplo, con ansible) o packer (en lugar de buildah y podman), yo tener algunos objetivos:

  • Ahorre recursos / No desperdicie recursos

    • No vuelvas a descargar constantemente el sistema operativo y los paquetes por idioma.

    • Guarde los recursos de ancho de banda de mi organización el índice del paquete.

  • Disponibilidad asegurada

    • Debería / debe funcionar sin conexión

    • Debe depender de tan pocos componentes como sea necesario

  • Asegurar la integridad de la construcción

    • Ser capaz de recrear la misma imagen con los mismos parámetros.

    • Aislar la varianza/Entregar compilaciones reproducibles

    • No controlamos recursos remotos como índices de paquetes.

    • No controlamos la ruta de la red.



      • DNSSEC y DNS sobre HTTPS probablemente no estén implementados correctamente



    • Podemos ser baneados y bastante limitados

    • Deberíamos usar sumas de verificación firmadas para verificar los recursos firmados



      • La autorización para acceder y firmar con claves se delega en algún lugar


      • Las variables ENtorno están disponibles para todos los procesos en el espacio de nombres del contenedor


      • Los montajes de volumen en tiempo de compilación son una forma de compartir las claves necesarias solo en el momento de la compilación (sin filtrarlas a la caché de imágenes)



  • Mantenga las compilaciones rápidas

    • Almacene en caché y memorice las operaciones frecuentes.

    • Los cachés agregan puntos de falla, variación potencial y riesgo de irreproducibilidad.



      • Caché de proxy HTTP (S!)


      • Caché de capa de aplicación a través de la red


      • Caché del sistema de archivos local



    • Implemente cachés tontos y descartables sin dependencias externas



      • Caché del sistema de archivos local



Si necesito vaciar el volumen de caché, puedo vaciar el volumen de caché.

0. Situación actual

RUN pip install app && rm -rf /root/.cache
  • posible hoy
  • O(n_builds): uso de ancho de banda
  • No funcionará sin conexión: depende de la red
  • Reconstrucciones más lentas

A. Copias

COPY . /app/src/app
COPY .cache/pip /app/.cache/pip
RUN pip install /app/src/app \
    && rm -rf /app/.cache/pip
  • posible hoy
  • ~O(1) ancho de banda del índice del paquete
  • O(n): en cada compilación (* ONBUILD )

    • Copia el caché

    • Desarchiva paquetes

    • Elimina el caché

  • Funciona sin conexión
  • Reconstrucciones más lentas

B. Bifurque y modifique cada Dockerfile desde arriba para agregar RUN --mount=type=cache y establecer una variable de entorno

# Fork by copying to modify every pip install line
RUN --mount=type=cache /app/.cache/pip pip install /app/src/pip
$ DOCKER_BUILDKIT=1 docker build . [...]
  • posible hoy
  • Esto ya introduce la irreproducibilidad: hay un parámetro extra-Dockerfile, extra-docker-compose.yml que introduce una variación en la salida: la imagen creada nombrada.
  • Documentos: cómo vaciar el caché --mount=type=cache (?)
  • ~O(1) ancho de banda del índice del paquete
  • Funciona sin conexión
  • Reconstrucciones rápidas

C. Especificar un volumen que se monta en el momento de la compilación

C.1. construir
$ buildah bud -v .cache/pip:/app/.cache.pip
  • posible hoy
  • También introduce la irreproducibilidad.
  • Documentos: cómo vaciar la memoria caché
  • ~O(1) ancho de banda del índice del paquete
  • Funciona sin conexión
  • Reconstrucciones rápidas
C.2. docker (lo que pide este problema)
C.2.1 CLI de la ventana acoplable
$ docker build -v .cache/pip:/app/.cache.pip
  • No es posible hoy
  • También introduce la irreproducibilidad.
  • Documentos: cómo vaciar la memoria caché
  • ~O(1) ancho de banda del índice del paquete
  • Funcionaría sin conexión
  • Reconstrucciones rápidas
C.2.2 docker componer
services:
  app:
    image: imgname:latest
    build: .
    build_volumes:  # "build_volumes" ?
    - ./.cache/pip:/app/.cache/pip
$ docker-compose build
  • No es posible hoy
  • También introduce la irreproducibilidad.
  • Documentos: cómo vaciar la memoria caché
  • Requeriría una revisión del esquema docker-compose
  • ~O(1) ancho de banda del índice del paquete
  • Funcionaría sin conexión
  • Reconstrucciones rápidas

...

  • COPIAR || FETCH_REMOTO || leer()

    • ¿Cuáles de estos son más reproducibles?

:point_up: Sólo un recordatorio. Puede anclar un archivo descargado comprobando su suma de comprobación. Algunos administradores de paquetes, como pip, también lo admiten.

@westurner Gracias por la explicación detallada.

Creo que lo siguiente sería similar a su caso B, pero podría borrar el caché y terminaría como su caso C2 (lo que está pidiendo, creo):

_docker-compose.yml:_

services:
  my-cache:
    build: ./my-cache
    image: local/my-cache

  my-image:
    build: ./my-image

_mi-caché/Dockerfile:_

FROM python

RUN pip install app

_mi-imagen/Dockerfile:_

FROM my-repo/my-image

RUN --mount=target=/export,type=bind,from=local/my-cache

RUN pip install /app/src/app

(https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#run---mounttypecache)

Puede construir la imagen de caché con:

docker-compose build my-cache

El comando RUN --mount=target=/export,type=bind,from=local/my-cache debe vincularse a la imagen. Si desea actualizar el caché, puede eliminar y reconstruir la imagen del caché.

Si esto todavía usa el caché en RUN --mount... , puede usar un archivo .env con una versión, incluya la versión en image: local/my-cache:$MY_VERSION y from=local/my-cache:$MY_VERSION (debería ser incluido como un argumento de compilación).

Puede incluir el servicio my-cache en otro archivo docker-compose si no desea que esté en el mismo archivo que sus servicios principales.

Todavía necesitaría usar DOCKER_BUILDKIT=1 (como en su caso B, pero creo que esto no será necesario en futuras versiones) y aún no sería reproducible (pero su caso C2 tampoco lo es).

¿Cuál sería la penalización que ves si no es reproducible? Si coloca la imagen de caché local/my-cache en docker hub (con un nombre de repositorio diferente) o en un registro privado y usa versiones para cada compilación (eso creará un caché diferente), con la misma versión teniendo siempre el mismo caché, ¿no lo haría reproducible ? Ni siquiera necesitaría incluir el servicio en el archivo docker-compose y llamar al comando de compilación. (Se debe acceder a Docker Hub desde la red, pero es lo mismo para sus otras imágenes, supongo, y después de descargar una vez, ya no debería ser necesario, a menos que genere una nueva versión con un nuevo caché)

DESCARGO DE RESPONSABILIDAD: No he probado el código anterior.

@Yajo El soporte de suma de comprobación en pip se implementó originalmente en 'peep' y luego se fusionó en pip. Puede agregar hashes buenos conocidos como fragmentos de URL en las entradas del archivo de requisitos de pip. (Hay fondos para mejoras de seguridad en el proyecto PyPA este año; el soporte TUF (The Update Framework; al igual que Docker Notary) en PyPI está planificado para finales de este año). Arrancar correctamente pip y PyPI (con claves y confianza) en imágenes acoplables probablemente será un tema a finales de este año.
(editar; un poco OT pero para los interesados) https://discuss.python.org/t/pypi-security-work-multifactor-auth-progress-help-needed/1042/

@lucasbasquotto Gracias por tu ayuda. Esto es significativamente más complicado que simplemente especificar --volume en el momento de la compilación. Es decir, parece requerir:

  • Especificando DOCKER_BUILDKIT=1 en el entorno de shell docker build
  • Modificar cualquiera/todas las instrucciones RUN de Dockerfile upstream con (editar) RUN --mount=type=cache y argumentos
  • ¿Acceso de lectura/escritura en otra imagen? ¡Mutabilidad! ¿O dicho caché está congelado con versiones probablemente obsoletas?

Si puedo COPIAR archivos del host o especificar parámetros de tiempo de compilación que no están almacenados en otro lugar, no veo cómo montar un volumen en el momento de la compilación es menos reproducible.

COPIAR || FETCH_REMOTO || leer()

  • ¿Cuáles de estos son más reproducibles?

@westturner

Especificar DOCKER_BUILDKIT=1 en el entorno de shell de compilación de docker

Si usa docker-compose , como vi en sus otras publicaciones, y si lo está ejecutando desde un contenedor, como:

$ sudo curl -L --fail https://github.com/docker/compose/releases/download/1.24.0/run.sh -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

Luego puede editar el archivo descargado en /usr/local/bin/docker-compose para usar esa variable env. Cambiar de:

exec docker run --rm $DOCKER_RUN_OPTIONS $DOCKER_ADDR $COMPOSE_OPTIONS $VOLUMES -w "$(pwd)" $IMAGE "$@"

para

DOCKER_BUILDKIT=1
exec docker run --rm $DOCKER_RUN_OPTIONS $DOCKER_ADDR $COMPOSE_OPTIONS $VOLUMES -w "$(pwd)" --env DOCKER_BUILDKIT=$DOCKER_BUILDKIT $IMAGE "$@"

Este es un cambio muy fácil y es transparente para quien ejecuta el comando.

_(Si no se ejecuta como contenedor, lo anterior no se aplica)_

Modificar cualquiera o todas las instrucciones RUN de Dockerfile upstream con RUN --cache y args

En el caso que expuse, sería RUN --mount=type=bind... , pero en cualquier caso, tener que cambiar el Dockerfile también es malo en mi opinión. Una opción -v realmente sería mucho mejor y más transparente .

¿Acceso de lectura/escritura en otra imagen? ¡Mutabilidad! ¿O dicho caché está congelado con versiones probablemente obsoletas?

Cuando vincula la imagen, probablemente creará un contenedor (o el nombre que sea, con un sistema de archivos replicado), y los cambios realizados allí durante la construcción no deberían cambiar la imagen original (no tendría sentido). Entonces, si construye usando una imagen de caché llamada my-repo/my-cache:my-version en una compilación, en la siguiente compilación sería exactamente igual (imutabilidad). Si desea usar un caché más actualizado, puede crear una nueva imagen con una nueva versión y usarla, como my-repo/my-cache:my-new-version .

¿Cuáles de estos son más reproducibles?

Considero reproducible como algo que sería exactamente igual incluso si lo ejecuta en otra máquina. En este sentido, si envía una imagen a un registro docker (seguro y confiable) y nunca cambia esa imagen, la consideraría reproducible (si tiene dudas sobre la conexión a Internet, puede usar un registro privado y acceder a él dentro de un VPN o algo así (nunca usé un registro privado)).

Si el comando COPY está copiando el caché de su máquina, no lo considero reproducible porque si ejecuta pip install (o apt-get , o lo que sea) en otra máquina, en otro momento, puede garantizar que el contenido del caché será el mismo? Tal vez esto podría ser una preocupación para usted. Tal vez no.

Por otro lado, si tiene archivos de su propiedad en algún lugar confiable que "posee" (como un cubo S3), descargue esos archivos en su máquina y cópielos con el comando COPIAR, luego puede reproducirlos desde otro máquina con los mismos resultados (asumiendo que los archivos no han cambiado, y la otra máquina es idéntica a la anterior). Así que consideraría esto como reproducible. Depende de dónde provengan esos archivos y cuánto control tenga sobre ellos.

La verdad sea dicha, no considero que nada sea 100% reproducible en todos los casos (al fin y al cabo, el hardware puede fallar), pero cuanto más fiable, mejor. Cuando me refiero a que algún proceso es reproducible, me refiero principalmente a que su contenido y resultado sean los mismos, y esto incluiría algo descargado de la red, suponiendo que los contenidos no cambien con el tiempo (no considero la posibilidad de que la red fracaso en este caso).

Hay algún tipo de error de red de Docker que hace que go mod download tampoco sea confiable dentro de un contenedor (al menos para aplicaciones de nuestro tamaño), por lo que solo ejecutarlo cada vez para descargar todo mi GOPATH/pkg/mod nuevamente es no sólo derrochador, sino roto. 🤷‍♀

¡Podría evitar una gran cantidad de copias innecesarias de archivos si pudiera usar --volume !

@kevincantu RUN --mount=type=cache debería cubrir su caso de uso

Eso requiere al menos una descarga exitosa de módulos desde dentro de una compilación de ventana acoplable, y en este caso particular aún no he visto eso ...

https://github.com/moby/moby/issues/14080#issuecomment -484314314 de @westurner es una descripción bastante buena, pero no pude hacer que buildkit funcionara:

$ sudo docker -v
Docker version 19.03.1, build 74b1e89

$ sudo DOCKER_BUILDKIT=1 docker build .
Ä+Ü Building 0.1s (2/2) FINISHED                                                                                                                
 => ÄinternalÜ load build definition from Dockerfile                                                                                       0.0s
 => => transferring dockerfile: 407B                                                                                                       0.0s
 => ÄinternalÜ load .dockerignore                                                                                                          0.0s
 => => transferring context: 2B                                                                                                            0.0s
failed to create LLB definition: Dockerfile parse error line 8: Unknown flag: mount

Mi Dockerfile comienza con # syntax=docker/dockerfile:experimental .

De hecho, me gustaría usarlo a través docker-compose . Probé ENV DOCKER_BUILDKIT 1 en el Dockerfile y también lo pasé de docker-compose.yml a través ARG DOCKER_BUILDKIT pero todo es lo mismo:

$ sudo docker-compose up --build
Building web
ERROR: Dockerfile parse error line 10: Unknown flag: mount

@lucasbasquotto ¿Cómo se traduciría lo que propuso en https://github.com/moby/moby/issues/14080#issuecomment -484639378 a una versión instalada de docker-compose?

Finalmente, ni siquiera estoy seguro de si esto cubriría mi caso de uso, tal vez algunos de ustedes puedan decirme si debo seguir con esto. Quiero usar un caché de tiempo de compilación para el desarrollo local que sobreviva entre compilaciones para que, al actualizar las dependencias, solo se deban descargar las nuevas. Así que agregaría RUN --mount=type=cache,target=/deps a Dockerfile y establecería la memoria caché del administrador de dependencias en /deps .

para docker compose, consulte https://github.com/docker/compose/pull/6865 , que estará en una próxima versión candidata de compose

Tengo otro caso de uso... Quiero construir contenedores para armar en un host x86_64 con binfmt configurado. Esto requiere que tenga el emulador de cpu qemu estático específico de la arquitectura en /usr/bin .

Mi solución actual es agregar qemu-arm-static en el contenedor como un archivo como:

FROM arm32v7/alpine:3.10
COPY qemu-arm-static /usr/bin/qemu-arm-static
RUN apk update && apk upgrade
RUN apk add alpine-sdk cmake
...

La solución más fácil sería montar mi archivo solo si es necesario dentro del contenedor como:
docker build -v /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static -t test:arm32v7 .
Esto funciona muy bien para la ejecución de la ventana acoplable, pero echo de menos esta funcionalidad para construir contenedores.

¿Existe otra solución para construir un contenedor de brazo en hosts x86_64 o podemos permitir volúmenes en el momento de la construcción al menos para este caso?

Los kernels más recientes de @jneuhauser permiten que estos archivos binarios se carguen estáticamente, por lo que no es necesario configurarlos cada vez. Puede lograr esto, por ejemplo, ejecutando la imagen linuxkit/binfmt en modo privilegiado una vez después del arranque.

Los núcleos más recientes permiten que estos archivos binarios se carguen estáticamente, por lo que no es necesario configurarlos cada vez.

@alehaa ¿Sin embargo, todavía no necesita el binario del emulador qemu estático dentro del contenedor?

@cybe Esto ya no es necesario, si se usa el indicador F (que es lo que hace el paquete linuxkit/binfmt ). Puedes encontrar más información sobre esto aquí .

¿Alguien podría proporcionar una configuración de trabajo para probar el kit de compilación? No puedo hacer que funcione en Ubuntu. Mi configuración es la siguiente:

cat /etc/docker/daemon.json

{
  "experimental": true
}

Dockerfile

# syntax=docker/dockerfile:experimental

FROM ruby:2.6.3

RUN --mount=type=cache,target=/bundle/vendor

sudo docker -v

Docker versión 19.03.1, compilación 74b1e89

DOCKER_BUILDKIT=1 sudo docker build .

Respuesta de error del daemon: línea de error de análisis de Dockerfile 12: indicador desconocido: montar

sudo no lleva env vars con él a menos que se lo indique con sudo -E o declare la variable dentro del sudo.

Escribí algunas palabras sobre esta función y creé algunos ejemplos mínimos que muestran cómo almacenar en caché

Editar: ver más abajo

@ cpuguy83 gracias!

@thisismydesign , lamento arruinar su entusiasmo, pero no puede --cache node_modules , no estará presente en la imagen final, por lo que su aplicación está rota.

@glensc Maldita sea, tienes razón ... ¿hay alguna manera de hacer que un caché de tiempo de compilación sea parte de la imagen final?

Honestamente, pensé que esto sería considerado para una función anunciada como

permite que el contenedor de compilación almacene en caché directorios para compiladores y administradores de paquetes.

Debería poder mapear ~/.npm en su lugar... https://docs.npmjs.com/files/folders.html#cache

@este es mi diseño

Sin embargo, puede usar otra imagen como caché, ya sea construyéndola en su Dockerfile o una imagen literal almacenada en un registro en algún lugar y use COPY --from

FROM example/my_node_modules:latest AS node_modules

FROM nodejs AS build
COPY --from=/node_modules node_modules 
...

Este es solo un ejemplo, puede usarlo para muchas cosas diferentes.

Ugh, odio mencionar esto e involucrarme aquí (también hola amigos)

pero tenemos un caso de uso para esto.


¿Hay un buen lugar donde pueda participar o una llamada o lista a la que pueda unirme para obtener un resumen aquí?

Además, si necesitamos a alguien que ponga algunos recursos en esto, tengo 1 kris nova y un pequeño equipo al que probablemente pueda persuadir para que mire esto.

TLDR ¿Puedo codificar esto, por favor? ¿Hay alguien con quien pueda hablar sobre esto?

_TLDR_ ¿Puedo codificar esto, por favor? ¿Hay alguien con quien pueda hablar sobre esto?

No puedo hablar por Docker, pero mi impresión es que no están abiertos a agregar montaje de volumen a las compilaciones (y que probablemente deberían cerrar este problema)

Muchos de los casos de uso de buildtime -v ahora están cubiertos por buildkit. A mi por lo menos me lo ha solucionado.

Revisaré el kit de compilación entonces: también tengo un hacky bash que hace el trabajo si alguien está interesado.

gracias @unilynx

+1 a @unilynx al cerrar este problema, buildkit también me resolvió los problemas de volumen de tiempo de compilación.

Apuesto a que si alguien dejara algunos enlaces y un ejemplo, podríamos convencer a nuestros amigos para que presionen el brillante botón de cerrar.


(Yo también me beneficiaría de ellos)

El caso de uso del almacenamiento en caché no está resuelto para mí y para muchos otros, ya que los volúmenes de tiempo de compilación con el kit de compilación no están presentes en la imagen final.

Así que pude sacar todos mis artefactos de compilación del volumen temporal usado en build tiempo y reconstruir la imagen nuevamente con el caché anterior usando este bash que mencioné anteriormente.

Pude reconstruir mi imagen encima de sí misma, de modo que el sistema de archivos de superposición solo tomó un pequeño delta.

Incluso pude reutilizar el volumen para otras imágenes en el momento de la compilación.


¿otras personas no pueden hacer esto?

(caché) los montajes están en el front-end "experimental"; descrito en https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md (a punto de ir a una reunión, pero puedo vincular ejemplos más extensos)

gracias @thaJeztah LMK si puedo ayudar aquí de alguna manera :)

https://github.com/moby/moby/issues/14080#issuecomment-547662701

@thisismydesign , lamento arruinar su entusiasmo, pero no puede --cache node_modules , no estará presente en la imagen final, por lo que su aplicación está rota.

@thaJeztah No creo que el problema anterior esté resuelto. Me encantaría echar un vistazo a algunos ejemplos en los que es posible almacenar en caché, por ejemplo npm install durante el tiempo de compilación que también permitirá que la imagen resultante use la instalación en caché.

@ kris-nova No resolví este problema pero, de nuevo, no estoy buscando usar scripts bash. Tal vez necesitemos un nuevo problema, pero este es un caso de uso bastante común que AFAIK aún no se ha resuelto.

@thaJeztah Aquí hay algunos ejemplos que usan montajes de caché que muestran cómo la imagen final no contendrá el montaje y no cubre muchos casos de uso de almacenamiento en caché en tiempo de compilación:

Para npm: ¿No se usarían los montajes de caché para el directorio de caché de npm (consulte https://docs.npmjs.com/cli-commands/cache.html, generalmente ~/.npm )?

@ankon Eso podría funcionar, gracias, lo intentaré. Otro caso de uso del que no estoy seguro es Bundler y Ruby.

Así que creo (aún no lo he probado) para Bundler que al menos puede deshacerse de la dependencia de la red usando un volumen de compilación en $BUNDLE_PATH y luego durante la compilación

bundle install
bundle package
bundle install --standalone --local

Básicamente, esto significa que tiene un directorio de instalación de paquetes en caché, desde allí empaqueta las gemas en ./vendor/cache y las vuelve a instalar en ./bundle . Pero esto no ahorra tiempo en la instalación y construcción de gemas, en realidad podría hacer que el paso de construcción sea más largo.

Si desea guardar los datos en caché en la imagen, cópielos en la imagen desde el caché.

Gracias, sin embargo, todavía es más una solución porque

  • tienes que hacer una copia adicional
  • Supongo que debe tener diferentes directorios entre los entornos de compilación y ejecución (no puede usar el directorio donde montó un volumen durante la compilación, ¿verdad?), por lo que requiere una configuración adicional

No sé cuánto esfuerzo sería simplemente tener una opción nativa para montar el mismo volumen en la imagen final, pero estoy bastante seguro de que facilitaría el uso. Estos son solo 2 ejemplos de lenguajes de script donde la forma de usar este caché no era obvia para mí. Ciertamente puedo imaginar que esto también surgirá en diferentes contextos.

@thisismydesign Parece que lo que quiere es poder compartir un caché entre la compilación y la ejecución.

buildkit es una solución solo para Linux, ¿qué hacemos en Windows?

@thisismydesign No estoy seguro de por qué espera que un montaje (caché) permanezca en la imagen final. No esperaría esto y no quiero tener ~ 1 gb en mi imagen solo por usar el montaje de caché de descarga.

buildkit es una solución solo para Linux, ¿qué hacemos en Windows?

Puede usar el kit de compilación en Windows.

https://docs.docker.com/develop/develop-images/build_enhancements/

Puede que le resulte más fácil establecer la configuración del daemon a través de la interfaz de usuario de Docker para Windows en lugar de establecer la variable de entorno antes de ejecutar.

@nigelgbanks en la parte superior de su enlace:

Only supported for building Linux containers

Oh, lo siento, asumí que estabas construyendo contenedores de Linux en Windows.

@thisismydesign Parece que lo que quiere es poder compartir un caché entre la compilación y la ejecución.

Eso resolvería mi caso de uso en torno al almacenamiento en caché, sí.

Hacer esto más fácil podría ahorrar millones de re-descargas de paquetes en CI
construye por año.

¿Algún servicio de CI es compatible con las características del kit de compilación experimental ?

El sábado 13 de junio de 2020 a las 14:08 Csaba Apagyi [email protected] escribió:

@thisismydesign https://github.com/thisismydesign Parece que
¿Quieres poder compartir un caché entre la compilación y la ejecución?

Eso resolvería mi caso de uso en torno al almacenamiento en caché, sí.


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/14080#issuecomment-643657987 , o
darse de baja
https://github.com/notifications/unsubscribe-auth/AAAMNS6IEQDCO5F3LNHJK5TRWO6AJANCNFSM4BJB2OOA
.

¿Algún servicio de CI es compatible con las características del kit de compilación experimental ?

¿Tienen que apoyarlo explícitamente? Estoy usando gitlab-ci con buildkit y simplemente funciona. Después de todo, es solo una forma diferente de invocar 'compilación de ventana acoplable'.

Por supuesto, a menos que traiga sus propios corredores a gitlab, las probabilidades de obtener un golpe de caché durante la compilación son bajas de todos modos.

Copiar desde una etapa con nombre de una compilación de varias etapas es otra solución

FROM golang:1.7.3 AS builder
COPY --from=builder

Pero la localidad de la imagen del contenedor sigue siendo un problema mayormente sin resolver para la programación de trabajos de CI

Los corredores tendrían que ser más pegajosos y compartir imágenes (intermedias) en un sistema de archivos común para minimizar las solicitudes innecesarias a repositorios de paquetes (perenialmente sin fondos suficientes).

Acabo de probar buildkit pero solo mejora marginalmente mi flujo de trabajo, que sería 100% ayudado por el volumen "real" o los montajes vinculados al host.

Estoy usando docker build para compilar versiones antiguas glibc que luego deberían ser parte de nuevos contenedores de compilación que proporcionen estos glibc para compilar y vincular.

Ahora la descarga repetida de la fuente glibc se resuelve mediante un montaje de enlace (desde buildkit ), el archivo solo se puede leer, no hay problema. Pero no tengo forma de acceder al directorio de compilación para el análisis después de compilaciones fallidas, ya que el contenedor se bombardea por error. (Si lo reinicio para acceder a él, reinicia la compilación, por lo que no ayuda).

Además, no veo por qué debería estar saltando a través de aros como construir un nuevo contenedor a partir de uno viejo solo para deshacerme de mi directorio de compilación, donde si el directorio de compilación hubiera sido un montaje en primer lugar, habría sido tan fácil. (Simplemente haga make install después de la compilación y tengo un contenedor limpio sin el directorio de compilación y sin las fuentes descargadas).

Así que sigo creyendo que esta es una solicitud de función muy válida y nos haría la vida mucho más fácil. El hecho de que se pueda abusar de una característica y podría romper otra funcionalidad si se usa, no significa que deba evitarse implementarla a toda costa. Solo considéralo un uso extra para una herramienta más poderosa.

Pero no tengo forma de acceder al directorio de compilación para el análisis después de compilaciones fallidas

Suena como una solicitud de función para buildkit. Esta es definitivamente una pieza faltante conocida.

Uno podría hacer esto hoy teniendo un objetivo para obtener el "directorio de compilación". Simplemente ejecutaría eso después de una ejecución fallida, todo aún debería almacenarse en caché, solo necesita el último paso para obtener los datos.
Sin embargo, entienda que esto es un poco una solución.

Además, no veo por qué debería estar saltando a través de aros como construir un nuevo contenedor a partir de uno viejo solo para deshacerme de mi directorio de compilación.

¿Puedes explicar más lo que quieres/esperas aquí?

¿Puedes explicar más lo que quieres/esperas aquí?

En este caso es solo querer matar 2 pájaros de 1 tiro:

  • tener una manera fácil de acceder a los resultados intermedios del host (aquí "construir análisis de directorios")
  • asegúrese de que este espacio de almacenamiento no contamine la imagen recién construida

Dado que este y todos los demás casos en los que el contenedor de compilación (así como la "compilación del contenedor") necesita hacer que la compilación sea lo menos dolorosa posible, se resolvería de manera mucho más elegante simplemente proporcionando la funcionalidad -v , tengo un difícil entender la resistencia para proporcionar esta función. Aparte de la funcionalidad "reconocimiento de caché" que aparentemente ofrece buildkit , solo puedo verlo como una forma enrevesada y engorrosa de lograr exactamente esta funcionalidad, y solo parcialmente. (Y en muchos casos donde el almacenamiento en caché es el objetivo principal, también se resolvería con -v , a costa de tener que bloquear el volumen montado en un contenedor específico mientras se ejecuta, pero el caché con buildkit tiene las mismas restricciones.)

¿Puedes explicar más lo que quieres/esperas aquí?

Estoy utilizando un proceso de compilación de varias etapas, en el que el propio entorno de compilación está en un contenedor y el resultado final es una imagen que contiene solo la aplicación y el entorno de tiempo de ejecución (sin las herramientas de compilación).

Lo que me gustaría es alguna forma para que el contenedor de compilación provisional de Docker envíe archivos de resultados de cobertura de código y prueba de unidad al sistema host en los eventos de una compilación exitosa y una compilación fallida, sin tener que pasarlos a la imagen de salida de compilación para la extracción (porque todo el proceso de compilación sufre un cortocircuito si las pruebas unitarias no pasan en el paso anterior, por lo que no habrá una imagen de salida en esa situación, y ahí es cuando más necesitamos los resultados de la prueba unitaria) . Me imagino que si se puede montar un volumen de host en el proceso de compilación de Docker, los comandos de prueba internos pueden dirigir su salida a la carpeta montada.

@mcattle
De hecho, muy similar también a (una de las funcionalidades) que necesito.
Desde que me mudé a buildah hace unos días, obtuve todas las funciones que necesitaba y más. La depuración de mi contenedor de compilación habría sido completamente imposible sin la posibilidad de ingresar de manera flexible al contenedor y los enlaces al host. Ahora soy un campista feliz. (Lamento interrumpir la fiesta con un "competidor", felizmente eliminaría este comentario si se ofende, pero fue una solución tan efectiva para los casos de uso presentados en este hilo que pensé que debería mencionarlo) .

No se ofende al decir que otra herramienta se adapta mejor a sus necesidades.

Si algo funciona para ti, eso es maravilloso.

Las deficiencias tanto del constructor v1 en Docker como del constructor del kit de compilación se entienden bastante bien en este contexto, y están buscando cómo abordarlas, preferiblemente sin tener que recurrir a montar montajes del cliente.
GitHub [email protected] escribió:
“@mcattle
De hecho, muy similar también a (una de las funcionalidades) que necesito.
Desde que me mudé a buildah hace unos días, obtuve todas las funciones que necesitaba y más. La depuración de mi contenedor de compilación habría sido completamente imposible sin la posibilidad de ingresar de manera flexible al contenedor y los enlaces al host. Ahora soy un campista feliz. (Lamento interrumpir la fiesta con un "competidor", felizmente eliminaría este comentario si se ofende, pero fue una solución tan efectiva para los casos de uso presentados en este hilo que pensé que debería mencionarlo) .”


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub o cancele la suscripción.

sin tener que recurrir a enlazar montajes desde el cliente.

Aquí explico por qué una opción de tiempo de compilación -v no recurre ni sacrifica la reproducibilidad más que depender de los recursos de la red en el momento de la compilación.

https://github.com/moby/moby/issues/14080#issuecomment-484314314 :

COPIAR || FETCH_REMOTO || leer()

  • ¿Cuáles de estos son más reproducibles?

Voy con buildah para el tiempo de compilación -v (y cgroupsv2) también.

@mcattle He tenido el mismo requisito. Lo resolví con el etiquetado .

Voy con buildah para el tiempo de compilación -v (y cgroupsv2) también.

Estoy considerando seriamente cambiar de Ubuntu (que solo tiene docker) a Fedora (que reemplazó a docker con podman/buildah) en nuestro servidor de compilación debido a la compatibilidad con "-v".

Por cierto. Podman también admite el modo sin raíz, y hasta ahora parece totalmente compatible con Docker (excepto por las diferencias en el impacto --usuario/USUARIO y el almacenamiento en caché de imágenes, que provienen del uso del modo sin raíz en lugar de ejecutarse como raíz como lo hace el demonio Docker).

PD. Si bien se necesita cgroups v2 para la operación sin raíz, el soporte para eso es más sobre el tiempo de ejecución del contenedor que sobre la ventana acoplable. Si usa CRun en lugar de RunC (como lo hace Fedora), tendría soporte para cgroups v2. RunC tiene soporte v2 y sin raíz en Git, pero tuve algunos problemas al probarlo en Fedora (31) hace unos meses.

EDITAR: Ubuntu tiene podman/buildah/etc en Groovy, pero no en la última versión 20.04 LTS, creo que se importó de Debian inestable. No se ha adaptado a LTS, al menos no todavía. Mientras que ha estado en Fedora desde 2018, creo.

@eero-t tal vez podría describir su caso de uso y lo que falta en las opciones que BuildKit proporciona actualmente que no se abordan para esos.

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