Moby: Solicitud de nueva función: deshabilite selectivamente el almacenamiento en caché para comandos RUN específicos en Dockerfile

Creado en 24 sept. 2013  ·  245Comentarios  ·  Fuente: moby/moby

derivando de la discusión del # 1384:

Entiendo que -no-cache deshabilitará el almacenamiento en caché para todo el Dockerfile. ¿Pero sería útil si puedo deshabilitar el caché para un comando RUN específico? Por ejemplo, actualizar repositorios o descargar un archivo remoto ... etc. Según tengo entendido, en este momento, ¿EJECUTAR apt-get update si se almacena en caché no actualizaría el repositorio? ¿Esto hará que los resultados sean diferentes a los de una máquina virtual?

Si se hace posible deshabilitar el almacenamiento en caché para comandos específicos en el Dockerfile, ¿los comandos subsiguientes en el archivo no usarían el caché? ¿O harían algo un poco más inteligente, por ejemplo, usar caché si el comando anterior produjo los mismos resultados (capa fs) en comparación con una ejecución anterior?

arebuilder kinfeature

Comentario más útil

¿Qué pasa con CACHE ON y CACHE OFF en el Dockerfile? Cada instrucción afectaría a los comandos posteriores.

Todos 245 comentarios

Creo que la forma de combatir esto es tomar el punto en el Dockerfile en el que desea almacenarlo en caché y etiquetarlo como una imagen para usar en su futuro Dockerfile FROM , que luego se puede construir con -no-cache sin consecuencias, ya que la imagen base no se reconstruiría.

Pero, ¿no limitaría esto el entrelazado de comandos almacenados en caché y no almacenados en caché con facilidad?

Por ejemplo, digamos que quiero actualizar mis archivos de repositorio y wget desde un servidor y realizar varios pasos intermedios, por ejemplo, instalar software desde el repositorio (que podría haberse actualizado), realizar operaciones en el archivo descargado (que podría haber cambiado en el servidor) etc.

Lo que sería ideal es una forma de especificar que la ventana acoplable en el Dockerfile ejecute comandos específicos sin caché cada vez y la única reutilización de la imagen anterior si no hay cambios (por ejemplo, no hay actualización en el repositorio).

¿No sería útil tener esto?

¿Qué pasa con CACHE ON y CACHE OFF en el Dockerfile? Cada instrucción afectaría a los comandos posteriores.

Sí, estoy usando los comandos git clone en mi Dockerfile, y si quiero que se vuelva a clonar con actualizaciones, necesito, como, agregar un comentario al final de la línea para activar una reconstrucción a partir de eso línea. No debería necesitar crear un contenedor base completamente nuevo para este paso.

¿Se puede pasar un ID de contenedor a 'compilación de docker' como una instrucción "no almacenar en caché más allá de este ID"? ¿De forma similar a la forma en que 'docker build' almacenará en caché todos los pasos hasta una línea modificada en un Dockerfile?

Estoy de acuerdo en que necesitamos un control más potente y detallado sobre la caché de compilación. Actualmente no estoy seguro de cómo exponer esto al usuario.

Creo que esto será más fácil con las próximas extensiones de API, específicamente la nomenclatura y la introspección.

Sería una gran característica. Actualmente estoy usando cosas tontas como RUN a=a some-command , luego RUN a=b some-command para romper el caché

Obtener un mejor control sobre la caché haría que el uso de la ventana acoplable de CI sea mucho más feliz.

@shykes

¿Qué hay de cambiar --no-cache de un bool a una cadena y hacer que tome una expresión regular de en qué parte de la ventana acoplable queremos romper la caché?

docker build --no-cache "apt-get install" .

Estoy de acuerdo y sugerí esta característica exacta en IRC.

Excepto que creo que para preservar la compatibilidad inversa deberíamos crear una nueva bandera (digamos "--uncache") para que podamos mantener --cached como una bandera bool (obsoleta) que se resuelve en "--uncache. *"

El viernes 7 de febrero de 2014 a las 9:17 a. M., Michael Crosby [email protected]
escribió:

@shykes
¿Qué hay de cambiar --no-cache de un bool a una cadena y hacer que tome una expresión regular de en qué parte de la ventana acoplable queremos romper la caché?

docker build --no-cache "apt-get install" .

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

¿Qué piensan los demás sobre esto? ¿Alguien quiere implementar la función?

Estoy dispuesto a intentar implementar esto hoy si nadie más ha comenzado.

Empecé a trabajar en él, quería validar que el enfoque se vea bien.

  • El campo noCache de buildfile convierte en *regexp.Regexp .

    • Un nil significa lo que solía hacer utilizeCache = true .

  • Pasar una cadena a docker build --no-cache ahora envía una cadena de expresión regular de validación al servidor.
  • Solo llamar a --no-cache da como resultado un valor predeterminado de .*
  • La expresión regular se usa luego en un nuevo método buildfile.utilizeCache(cmd []string) bool para verificar los comandos que ignoran el caché

Una cosa: por lo que puedo ver, el paquete flag / mflag no admite marcas de cadena sin un valor, por lo que tendré que hacer algunos retoques adicionales para admitir tanto --no-cache como --no-cache some-regex

Realmente creo que esta debería ser una nueva bandera separada. El comportamiento y la sintaxis de --no-cache ya están bien definidos y son utilizados en muchos, muchos lugares por muchas personas diferentes. Votaría por --break-cache o algo similar, y haría que --no-cache hiciera exactamente lo que hace hoy (ya que ese es un comportamiento muy útil en el que muchas personas confían y aún quieren).

De todos modos, IANTM (no soy el mantenedor), así que estos son solo mis pensamientos personales. :)

@tianon --no-cache actualmente es bool, por lo que esto simplemente extiende el comportamiento existente.

  • docker build --no-cache - mismo comportamiento que antes: ignora el caché
  • docker build --no-cache someRegex - ignora cualquier comando RUN o ADD que coincida con someRegex

Bien, está todo bien. El problema es que --no-cache es un bool, por lo que el comportamiento existente es en realidad:

  • --no-cache=true - deshabilitar explícitamente el caché
  • --no-cache=false - habilitar explícitamente el caché
  • --no-cache - taquigrafía de --no-cache=true

También creo que nos estaríamos haciendo un flaco favor al hacer cadenas de expresiones regulares de casos especiales "verdaderos" y "falsos" para resolver esto, ya que eso creará un comportamiento potencialmente sorprendente para nuestros usuarios en el futuro. ("Cuando uso --no-cache con una expresión regular de 'verdadero' o 'falso', ¡no funciona como debería!")

@tianon, sí, tienes razón. Eché un vistazo rápido y la gente está usando = verdadero / falso.

Feliz de modificar el PR para agregar una nueva bandera como sugiere, ¿qué piensan los mantenedores ( @crosbymichael , @shykes)? Esto también significaría que podría eliminar el código agregado a mflag para permitir banderas de cadena / bool.

+1 para el enfoque de @wagerlabs

@crosbymichael , @timruffles ¿No sería mejor si el autor del Dockerfile decide qué paso de compilación debe almacenarse en caché y cuál no? La persona que crea el Dockerfile no es necesariamente la misma que crea la imagen. Mover la decisión al comando docker build exige un conocimiento detallado de la persona que solo quiere usar un Dockerfile específico.

Considere un entorno corporativo donde alguien solo quiere reconstruir una jerarquía de imágenes existente para actualizar algunas dependencias. El árbol de Dockerfile existente puede haber sido creado hace años por otra persona.

+1 para el enfoque de @wagerlabs

+1 para el enfoque de @wagerlabs , aunque sería aún mejor si hubiera una forma de almacenar en caché la ruptura en un intervalo de tiempo, por ejemplo

CACHE [interval | OFF]
RUN apt-get update
CACHE ON

Aprecio que esto podría ir en contra de la idea de que los contenedores no son deterministas, sin embargo, es exactamente el tipo de cosas que desea hacer en un escenario de implementación continua donde su canalización tiene buenas pruebas automatizadas.

Como solución alternativa, actualmente estoy generando destructores de caché en el script que utilizo para ejecutar la compilación de la ventana acoplable y agregarlos en el archivo de la ventana acoplable para forzar una ruptura de la caché

FROM ubuntu:13.10
ADD ./files/cachebusters/per-day /root/cachebuster
...
ADD ./files/cachebusters/per-build /root/cachebuster
RUN git clone [email protected]:cressie176/my-project.git /root/my-project

Estoy buscando usar contenedores para la integración continua y la capacidad de establecer tiempos de espera en elementos específicos en la caché sería realmente valiosa. Sin esto no puedo desplegarme. Forzar una reconstrucción completa cada vez es demasiado lento.

Mi plan actual para solucionar esto es inyectar dinámicamente comandos como RUN echo 2014-04-17-00:15:00 con la línea generada redondeada a los últimos 15 minutos para invalidar los elementos de la caché cuando el número redondeado salta. ala cada 15 minutos. Esto funciona para mí porque tengo un script que genera el dockerfile cada vez, pero no funcionará sin ese script.

+1 para la función.

También quiero votar por esta función. El caché es molesto cuando se construyen partes de un contenedor a partir de repositorios de git que se actualizan solo en la rama maestra.
: +1:

@hiroprotagonist ¿ Tener un git pull en tu ENTRYPOINT podría ayudar?

@amarnus Lo he resuelto de forma similar a la idea que tenía @tfoote . Estoy ejecutando la compilación desde un trabajo de jenkins y en lugar de ejecutar el comando docker build directamente, el trabajo inicia un skript de compilación que genera el Dockerfile a partir de una plantilla y agrega la línea 'RUN echo currentsMillies' encima de los comandos de git. Gracias a sed y tuberías, esto fue cuestión de minutos. De todos modos, sigo favoreciendo esta función como parte del propio Dockerfile.

Agregando mi +1 para el enfoque de @wagerlabs . También tengo este problema con CI. Simplemente estoy usando una declaración de EJECUCIÓN de eco dinámica por el momento, pero me encantaría esta función.

+1 para CACHE ENCENDIDO / APAGADO. Mi caso de uso también es la automatización de CI.

+1, especialmente la capacidad de establecer un intervalo de caché de comandos de ejecución como en el ejemplo de @ cressie176

"Por ejemplo, actualizar repositorios o descargar un archivo remoto"

+1

Si ayuda a alguien, aquí está el fragmento de código que estoy usando en mi compilación de Jenkins:

echo "Using build $BUILD_NUMBER for docker cachebusting"
sed -i s/cachebust_[0-9]*/cachebust_"$BUILD_NUMBER"/g Dockerfile

+1 para CACHE ENCENDIDO / APAGADO

Como posible alternativa al enfoque CACHE ON / OFF, ¿qué tal una palabra clave adicional como "SIEMPRE"? La palabra clave se usaría en combinación con un comando existente (por ejemplo, "SIEMPRE EJECUTAR" o "SIEMPRE AGREGAR"). Por diseño, la palabra clave "SIEMPRE" no va al caché para completar el comando adyacente. Sin embargo, compara el resultado con el CACHE (implícitamente el caché en otras ocasiones en que se ejecutó la misma línea), vinculando a la imagen en caché si el resultado del comando SIEMPRE no cambia.

Creo que la necesidad subyacente es identificar "instrucciones no idempotentes" . El comando SIEMPRE hace esto de manera muy explícita. Mi impresión es que el enfoque CACHE ON / OFF podría funcionar igualmente bien, pero también podría requerir muchos cambios de bloques de código (lo que puede alentar a los usuarios a bloquear más líneas de las que realmente se requieren).

También estoy más por un prefijo a los comandos, como SIEMPRE o CACHE 1 WEEK ADD ...

Así que estuve luchando con este problema por un tiempo y solo quería compartir mi trabajo en caso de que sea útil mientras se soluciona. Realmente no quería agregar nada fuera del archivo de la ventana acoplable a la invocación de compilación o cambiar el archivo cada vez. De todos modos, este es un ejemplo tonto, pero usa el mecanismo de adición para romper el caché y no requiere ninguna manipulación de archivos.

From ubuntu:14.04

RUN apt-get -yqq update
RUN apt-get -yqq install git
RUN git clone https://github.com/coreos/fleet
ADD http://www.random.org/strings/?num=10&len=8&digits=on&upperalpha=on&loweralpha=on&unique=on&format=plain&rnd=new uuid
RUN cd fleet && git pull

Obviamente, puede elegir su propio caso de uso y generación aleatoria de red. De todos modos, tal vez ayude a algunas personas a salir.

Otro +1 para el enfoque de @wagerlabs

Otro +1 a la función. Mientras tanto, usando la solución alternativa @cruisibesarescondev .

uno más +1 para la solicitud de función. Y gracias a @cruisibesarescondev por la solución

Otro +1 para la función.

Saludos a @cruisibesarescondev por la solución.

Creo que la palabra clave SIEMPRE es un buen enfoque, especialmente porque tiene una semántica simple y clara. Un enfoque un poco más complicado sería agregar un tiempo mínimo (útil en cosas como una granja de construcción o una integración continua). Para eso, propondría una sintaxis "CADA XXX" donde XXX es un tiempo de espera. Y si ha pasado más de XXX desde que se creó la caché de ese comando, debe volver a ejecutar el comando. Y compruebe si la salida ha cambiado. Si no hay cambios, reutilice el resultado almacenado en caché, teniendo en cuenta la última hora actualizada. Esto significaría que CADA 0 sería lo mismo que SIEMPRE.

Para una solución en este momento, genero mis Dockerfiles usando plantillas vacías en Python e incrusto los siguientes fragmentos que funcionan como arriba, excepto que no detecta el mismo resultado en dos ejecuciones sucesivas, pero fuerza un reactivación cada XXX segundos. En la cima:

@{
import time
def cache_buster(seconds):
    ts = time.time()
    return ts - ts % seconds
}@

Donde quiero forzar una repetición:

RUN echo @(cache_buster(60))

Que se ve así en el Dockerfile

RUN echo 1407705360.0

Como puede ver, se redondea a los 60 más cercanos, por lo que cada vez que pasan 60 segundos, la siguiente ejecución volverá a ejecutar todos los comandos siguientes.

+1 para SIEMPRE sintaxis. +.5 para CACHE ON / CACHE OFF.

+1 para SIEMPRE sintaxis.

Sí, SIEMPRE la sintaxis parece muy intuitiva.

No me gusta CACHE ON / OFF porque creo que las líneas deberían ser "autónomas" y agregar bloques a Dockerfiles introduciría muchos "problemas" (como tener que verificar "¿esta línea está cubierta por caché?" Al fusionar ... .).

@kuon Creo que ya hay una serie de comandos que afectan a las instrucciones posteriores, por ejemplo, USER y WORKDIR

Sí, es cierto, pero no los uso por la misma razón. Siempre hago RUN cd ... && o RUN su -c ...&& .

Preferiría una notación de bloque:

CACHE OFF {
    RUN ...
}

Esto es más explícito y evita tener una línea CACHE OFF insertada por error (desencadenaría un error de sintaxis).

Puede que lo esté pensando demasiado, los archivos Dockerfiles no se ejecutan realmente en producción (solo cuando se crea la imagen), por lo que tener el caché deshabilitado cuando se compila no hará mucho daño. Pero también siento que los archivos Dockerfiles son realmente limitantes (tener que encadenar todos los comandos con un && en una sola EJECUCIÓN para evitar crear una gran cantidad de imágenes, no poder usar variables ...).

Quizás este problema sea la oportunidad para un nuevo formato de Dockerfile.

Me gustaría volver sobre lo que acabo de decir. Leí lo que dijo @shykes en otro número https://github.com/docker/docker/pull/2266 y también estoy de acuerdo con él (Dockerfile debe seguir siendo un lenguaje ensamblador realmente simple).

Dije que me gustaría una variable o cosas así, pero eso puede ser cubierto por algún otro lenguaje, pero en este caso, cada línea en un Dockerfile debe ser autónoma, por ejemplo:

NOIMAGE ALWAYS RUN USER:jon  apt-get update

Que siempre ejecutaría el comando (sin caché), pero tampoco crearía una imagen y usaría el usuario jon.

Este tipo de línea autónoma es mucho más fácil de generar desde cualquier otro idioma. Si tiene que preocuparse por el contexto (usuario, caché, workdir), es más propenso a errores.

¿Puede ser RUN! para facilitar, por favor?

¿Alguna actualización de estado sobre este?

Deshabilitar selectivamente la caché sería muy útil. Tomo archivos de un repositorio remoto de amazon s3 a través del comando awscli (del kit de herramientas de Amazon AWS), y no tengo una manera fácil de romper el caché a través de un comando ADD (al menos no puedo pensar en una manera sin editar el Dockerfile para activarlo). Creo que hay un caso sólido para devolver el control al usuario para romper selectivamente el caché cuando usa RUN. Si alguien tiene una sugerencia para mí, me encantaría saber de usted.

Quería aumentar un poco este problema, ya que es algo que tenemos una gran necesidad.

Aún estoy convencido de que la sintaxis ALWAYS es la ideal.

¿Qué tal una simple declaración BREAK ?

@ cpuguy83 que funcionaría también para mi caso de uso particular.

No estoy seguro de si es técnicamente posible que solo un comando no se almacene en caché, pero el resto de ellos se almacenen en caché. Probablemente no, ya que la ventana acoplable se basa en diferencias incrementales.

Sin embargo, tener soporte para BREAK me daría paridad de características con mi solución actual basada en la sugerencia de @CheRuisiBesares.

Con respecto a mi publicación anterior, de hecho sería suficiente simplemente romper el caché desde ese punto en el script en adelante, el resto simplemente se reduciría al diseño inteligente del script (y creo que esto abordaría los requisitos de la mayoría de las personas). ¿Es esto factible en lugar de deshabilitar selectivamente el busto de caché?

@orrery Probablemente podría " COPY _antes_ de ese paso de compilación. Si los archivos copiados son diferentes, todos los pasos posteriores ya no deberían usar la caché (consulte esta sección ). Truco sucio, pero puede resolver tu caso.

Una clave para ALWAYS (o conceptos similares como EVERY # DAYS ) es la comparación de caché después del comando adjunto. Para mí (y supongo que para muchos otros), el objetivo no es romper el caché per se.

  • El objetivo es asegurarnos de que dejemos de usar la caché si cambia el resultado del comando (es decir, "actualizar a la versión más reciente").
  • Por el contrario, si el resultado coincide con una versión en caché, queremos aprovechar la caché.

Esto aborda el comentario de @hellais ya que puede aprovechar la caché para los comandos posteriores ... si y solo si la salida de ALWAYS coincide con una versión en caché (esto podría ser fácilmente la mayoría de las veces).

Naturalmente, la misma lógica _podría_ incluirse en un modelo CACHE ON / OFF. Es probable que la comparación con la caché sea más barata que volver a ejecutar todos los comandos posteriores, pero aún así podría resultar costosa. Si un bloque CACHE ON / OFF anima a un usuario a incluir comandos adicionales en un bloque OFF (algo que no puede suceder con ALWAYS ), podría contribuir a diferencias significativas en el rendimiento.

Estoy exactamente en la misma situación que @tfoote : estoy usando Docker para CI y necesito forzar la caducidad de la caché.

+1 para la sintaxis EVERY . La sintaxis ALWAYS también haría el trabajo.

@claytondaley, ese es un gran punto. Sin embargo, sigue siendo importante tener la capacidad de deshabilitar por completo el almacenamiento en caché de un comando. Siempre habrá un estado oculto que es inherentemente invisible para Docker. Por ejemplo, la ejecución de un comando puede cambiar de estado en un servidor remoto.

@mkoval , mencionas un buen punto sobre _crear _ estados ocultos como un momento importante para usar ALWAYS , pero no creo que afecte mi lógica sobre la reanudación de la caché. Para que el ejemplo sea concreto (aunque algo trivial), un comando que actualiza un sistema de terceros:

  • Crea un estado oculto (debe ejecutarse ALWAYS ) y
  • No cambia el contenedor actual

Si el siguiente comando no implica un estado oculto (trivialmente, un comando mv en el contenedor), la caché será 100% confiable. Mismo contenedor, mismo comando, sin dependencia de información oculta.

Si el siguiente comando (o cualquier comando posterior) involucra información oculta, entonces debe usar la palabra clave ALWAYS , solo reanudando el caché si el contenedor resultante coincide con el caché.

@claytondaley, tu solución me parece muy elegante y eficiente. Estaría muy agradecido si esto se implementara. : +1:: pulpo:

+1 para esta función usando SIEMPRE y CADA X sintaxis sugerida. CACHE ON / OFF me parece un poco torpe, pero lo usaría. También me gusta mucho la sugerencia de

+1 para SIEMPRE sintaxis. especialmente para códigos de extracción de git repo.

+1 Para cualquiera de estas soluciones.

Estoy un poco confundido. ¿Cómo se puede volver a activar el almacenamiento en caché una vez que se ha desactivado? Una vez que lo apague y realice algún tipo de cambio en el contenedor, ¿no eliminaría básicamente los cambios realizados por los comandos de Dockerfile que se ejecutaron mientras el almacenamiento en caché estaba desactivado? Pensé que la razón por la que podíamos hacer el almacenamiento en caché era porque conocíamos exactamente la lista completa de comandos anteriores que se ejecutaron y podíamos garantizar que lo que había en el contenedor era exactamente el mismo. Si desactiva el almacenamiento en caché (y estoy hablando del lado de búsqueda), ¿eso no elimina esa garantía? ¿O se trata simplemente de no llenar el caché?

Según entiendo las sugerencias, puede especificar "SIEMPRE" como parte de un comando de Dockerfile para ejecutar siempre el paso nuevamente. Por ejemplo, "EJECUTAR SIEMPRE git clone https://example.com/myrepo.git " siempre se ejecutará (por lo tanto, siempre se clona el repositorio). Entonces, lo que sugiere @claytondaley es que después de ejecutar este comando nuevamente, Docker verifica los cambios en el caché. Si la suma de comprobación es la misma (es decir, si el repositorio clonado no tuvo cambios, por lo que la capa más nueva es idéntica a la misma capa en la caché), podemos continuar con la caché activada. Tiene razón en que una vez que se invalida el caché, todos los pasos posteriores no pueden usar el caché. Estas sugerencias solo permiten una mayor granularidad de control sobre cuándo usar la caché, y también es inteligente al reanudar desde la caché siempre que sea posible.

@curtiszimmerman ... exactamente

@duglin ... La idea puede ser más obvia si usamos un proxy matemático. El caché (en este contexto) es solo la memoria del resultado de action B cuando se aplica a state A para que no tenga que volver a procesarlo. Supongamos que ejecuto una secuencia de comandos:

  • empezar con 6
  • SIEMPRE ejecute * x donde el valor de x se descarga desde un repositorio de git (y por lo tanto podría cambiar)
  • ejecutar + 12

La primera vez que ejecuto el comando, x es 8, así que obtengo (y guardo en caché) la siguiente secuencia:

  • 6
  • 48 (como resultado de * x aplicado a 6 )
  • 60 (como resultado de + 12 aplicado a 48 )

Si mi máquina alguna vez alcanza el estado 48 nuevamente (por cualquier secuencia) ... y se le da el comando + 12 , no tengo que volver a hacer el procesamiento. Mi caché sabe que el resultado de este comando es 60 .

La parte difícil es averiguar cuándo estás en el mismo estado ( 48 ) nuevamente.

  • En teoría, podríamos comparar la máquina después de cada comando con cualquier otra imagen almacenada en caché, pero esto requiere muchos recursos y tiene muy pocas probabilidades de encontrar una coincidencia.
  • Mi propuesta es que sea sencillo. Cada vez que estamos en un estado (por ejemplo, 6 ) y presionamos un comando (por ejemplo, * x ) comparamos el resultado con el caché de la última vez (o veces) que estuvimos en el mismo estado ejecutando el mismo comando. Si el estado de la máquina después de este proceso es el mismo (por ejemplo, todavía 48 ), reanudamos la caché. Si el siguiente comando sigue siendo + 12 , extraemos el resultado del caché en lugar de procesarlo.

@claytondaley, pero no entiendo cómo se determina el estado actual. Como dijiste, no comparamos todos los archivos del contenedor. La forma en que funciona el caché ahora es básicamente simplemente strcmp el siguiente comando que queremos ejecutar contra todos los contenedores secundarios conocidos del contenedor actual. En el momento en que omite un contenedor en el flujo, no veo cómo puede asumir que su contenedor actual es como cualquier otro contenedor en caché sin verificar todos los archivos en el sistema de archivos. Pero quizás no asimilo lo que estás haciendo.

Déjame reformularlo ... dado un contenedor aleatorio (que es básicamente lo que tienes si no estás usando el caché), ¿cómo puedes encontrar un contenedor en el caché que coincida sin diferenciar todos los archivos en el ¿envase?

@claytondaley @duglin Determinar si una operación "sin caché" se puede almacenar en caché debido a que no hay cambios es un problema difícil, como lo ha descrito. También es más agradable tener que estrictamente necesario.

Personalmente, estaría más que feliz si todo lo que tuviera fuera la capacidad de garantizar que un comando siempre se ejecute. Tome un Dockerfile como:

RUN install_stuff_take_forever
RUN always_do_it   #will not run every time
RUN more_stuff

Actualmente, la línea always_do_it solo se ejecutará la primera vez, a menos que edite el texto para forzar una ruptura de caché. Creo que la mayoría de nosotros estaría feliz de aceptar que more_stuff a veces se ejecutará innecesariamente (cuando always_do_it no ha cambiado, si a cambio podemos mantener el caché por install_stuff_take_forever .

RUN install_stuff_take_forever
NOCACHE
RUN always_do_it
RUN more_stuff

@pikeas Obtengo totalmente un comando NOCACHE y eso es fácil de hacer. Lo que no obtengo es un comando que lo vuelve a activar sin diffing / hashing / cualquiera que sea el sistema de archivos completo.

Leí la explicación de la

  • Docker crea una "capa" para cada comando.
  • Esa capa incluye solo los archivos modificados (o posiblemente "guardados", ya sea que hayan cambiado o no) por ese comando.
  • El estado actual del sistema de archivos se logra de manera lógica (si no operativa) al verificar cada capa en orden hasta que encuentre una versión (la más actualizada) de ese archivo en particular.

En este caso, una comparación de dos instancias del mismo comando es relativamente barata. Solo necesita comparar la capa superior (ya que todas las capas subyacentes se comparten). Hay una lista específica de archivos que fueron modificados por el comando. Solo esos archivos se incluyen en la capa. De acuerdo ... necesitaría comparar todos los archivos en esa capa ... pero no todo el sistema de archivos.

También es posible (aunque no se garantiza que sea exhaustivo) comparar solo la nueva capa con la última vez que se ejecutó el comando:

  • En la mayoría de los casos (git pull o actualización de software), la versión actual será (1) la misma que las últimas versiones o (2) una nueva versión ... pero nunca, al menos en raras ocasiones, una reversión a una anterior. versión.
  • En casos excepcionales (como actualizar a dev-master y luego volver a una versión estable), es posible volver a cambiar a una versión anterior. Sin embargo, estos son bastante raros, por lo que la mayoría de las personas probablemente estarían mejor (con frecuencia) verificando solo la versión más reciente y volviendo a ejecutar los comandos en el raro caso de que se deshagan.

Por supuesto, también puede hacer una verificación de hash en todas las versiones anteriores ... seguido de una verificación de archivo completo ... para ofrecer soporte completo sin gastos generales.

Si miras la parte inferior de https://github.com/docker/docker/pull/9934 , verás una discusión sobre las opciones de soporte para los comandos de Dockerfile. ¿Qué pasaría si hubiera una opción --no-cache disponible en todos (o incluso solo en EJECUTAR) que significara "no usar el caché" para este comando? p.ej:
EJECUTAR --no-cache apt-get install -y my-favorite-tool
Esto también deshabilitaría automáticamente el caché para los comandos restantes (creo).
¿Resolvería esto el problema?

Entre "EJECUTAR SIEMPRE" y "EJECUTAR --no-cache", que son semánticamente idénticos, personalmente preferiría la sintaxis de "EJECUTAR SIEMPRE" de apariencia más natural. Estoy de acuerdo con el último comentario sobre ese PR: Creo que --option rompe la legibilidad y hará que Dockerfiles sea feo. Además, creo que los comandos de Dockerfile deberán ser muy distintos frente a los comandos reales que los siguen. Imagine algo como "EJECUTAR --no-cache myapp --enable-cache" para un ejemplo de sintaxis complicada que comenzaría a expresarse rápidamente con ese tipo de opción.

@curtiszimmerman, tu ejemplo es muy claro para mí. --no-cache es para RUN mientras que --enable-cache es para myapp. La ubicación importa. Por ejemplo, mira:
Docker ejecutar -ti ubuntu ls -la
la gente entiende que -ti es para 'correr' mientras que '-la' es para 'ls'. Esta es una sintaxis con la que la gente parece sentirse cómoda.
Uno de los problemas con algo como EJECUTAR SIEMPRE es la extensibilidad. Necesitamos una sintaxis que pueda funcionar para todos los comandos de Dockerfile y que admita la transferencia de valor. Por ejemplo, la gente ha expresado interés en especificar el USUARIO para ciertos comandos.
EJECUTAR USUARIO = foo myapp
técnicamente está configurando un USER de env var en 'foo' dentro del shell de myapp. Entonces somos ambiguos aquí.
Mientras: RUN --user = foo myapp no ​​tiene este problema.
Es: RUN var = foo myapp
tratando de establecer y env var llamado 'var' o un error tipográfico tratando de obtener alguna opción RUN?
IOW, las probabilidades de superponerse con un comando válido existente, IMO, son mucho menores cuando comenzamos con, que simplemente permitir una palabra allí

De hecho, defiendo la secuencia inversa, EVERY <options> COMMAND . Muchas rasones:

  • En el caso de "usuario" y "caché" (al menos), en realidad son características del entorno que podrían envolver cualquier COMANDO (aunque es posible que no afecten materialmente a otros).
  • La sintaxis RUN ALWAYS significa cambiar el intérprete de comandos RUN , que suena innecesario.
  • Este problema es aún peor con RUN EVERY 5 days porque las opciones adjuntas a TODOS crean aún más ambigüedad. EVERY 5 days RUN tiene claro el comando al que afectan las opciones. Tenemos el mismo problema con RUN USER usr frente a USER usr RUN . Siempre que (1) las palabras clave de comando nunca sean opciones o (2) haya una manera fácil de escapar de ellas, esto no es ambiguo.

Podría sumarme al prefijar los comandos con sus opciones ( ALWAYS AS user RUN ... ). Solo estoy realmente preocupado por usar longgopts estilo GNU para las opciones porque no están muy separados de los ojos viejos o vidriosos. Me puedo imaginar mirando un comando complejo de Dockerfile después de 20 horas preguntándome qué está pasando. Pero predigo que las opciones sucederán independientemente.

Pero predigo que las opciones sucederán independientemente.

Aún no se ha decidido nada, al contrario; la sintaxis que sugiere @duglin es una _propuesta contraria_ a una sintaxis que se propuso / decidió anteriormente. Lea el número 9934 para obtener más información al respecto.

Además, @duglin _no_ es la persona que toma esa decisión (al menos, no está sola). Algunos de los puntos que está planteando se han mencionado en el otro hilo.

Comparto su preocupación por la legibilidad, pero también creo que las otras sintaxis que se propusieron podrían tener el mismo problema si se deben especificar varias opciones.

Este problema posiblemente se puede solucionar formateando el Dockerfile para que sea legible. Creo que sería bueno escribir algunos ejemplos más para probar / verificar si la legibilidad es una preocupación cuando se formatea correctamente.

Y sí, sus comentarios son bienvenidos.

Todavía soy muy -1 en dejar que el Dockerfile defina dónde está el caché
debe y no debe aplicarse. Todavía tengo que ver un buen ejemplo de
Dockerfile que no se pudo reescribir en cache-bust de manera apropiada y
naturalmente, cuando era necesario actualizar el recurso subyacente.

Tener una marca en "compilación de la ventana acoplable" para detener el caché en un lugar en particular
sería mucho más flexible, en mi opinión (y devolvería el control del caché
en manos del operador del sistema que se encarga de administrar ese caché de todos modos).

+1 en el -1 de @tianon (¡así que es un -1!), Y agregar una bandera para romper en el paso N parece razonable. Teniendo en cuenta que una vez que la caché está rota, de todos modos está rota para el resto del Dockerfile, creo que esto tiene sentido.

La principal necesidad de esto se debe a que el mecanismo de almacenamiento en caché de la ventana acoplable está directamente vinculado al almacenamiento y transporte de la imagen, lo que permite un almacenamiento en caché eficiente, pero a cambio de imágenes significativamente más grandes. ¡Así que arreglemos eso!

Sin decir cómo me siento acerca de esta función, todavía no estoy seguro, para ser honesto, ¿cómo imaginan que alguien diga (de "docker build") que se detenga en el paso N? Parece un poco frágil cuando hoy el paso N sería el paso N + 1 mañana.
Parece que es posible que necesitemos una forma de agregar una "etiqueta" de algún tipo dentro del Dockerfile para que la gente pueda hacer referencia a esa etiqueta desde la línea cmd de compilación.
Si tuviéramos eso, entonces no estoy seguro de ver mucha diferencia entre eso y agregar un comando "STOP-CACHING" que aparece en el Dockerfile.
¿Cuál es un buen ejemplo de un cmd de Dockerfile que romperá el caché cada vez?

Bueno, en realidad es por eso que se discutió originalmente para convertirlo en un
regexp basado en contenido de línea, con el que también estaría bien (especialmente porque
eso es mucho más fácil de escribir que saber exactamente qué número de paso
no quiero que se almacene en caché, de ninguna manera estoy escribiendo una copia completa de la
Analizador de Dockerfile en Bash, gracias: D).

Tianon Gravi [email protected] escribió:

Bueno, en realidad es por eso que se discutió originalmente para convertirlo en un
expresiones regulares basadas en contenido de línea, con las que también estaría bien (especialmente
ya que
eso es mucho más fácil de escribir que saber exactamente qué número de paso
Uds
no quiero que se almacene en caché, de ninguna manera estoy escribiendo una copia completa de la
Analizador de Dockerfile en Bash, gracias: D).

Me gustaría reafirmar mi sugerencia anterior, que SIEMPRE / ruptura de caché
"RUN" debería ser simplemente "RUN!" para mantener la estructura de comando de 1 palabra (?).

Parece complicado tener que editar un Dockerfile (agregando algo que es básicamente aleatorio porque es un marcador de posición) para romper el caché en un paso específico. Usaría una opción docker build CLI que siempre ejecuta un cierto paso, pero estoy totalmente de acuerdo con @duglin en que tener que rastrear el número de línea específico para git clone solo para presionar a Docker para que realmente clone el repositorio en lugar de trabajar desde el caché.

@curtiszimmerman Sugerí (!) porque indica algo parecido a la urgencia en inglés. ("¡Usted debe hacer esto!")

Creo que Dockerfile es al menos un lugar apropiado para definir qué comandos no deben poder almacenarse en caché. Tener que construir con "--no-cache = git" (me doy cuenta de que esto no es algo que sugirió, pero no me sugirió nada para citar / comparar) parece más torpe.

¿Por qué centrarse en RUN? ¿Por qué no permitir que se rompa la caché para cualquier comando?
Parece agregar un:
BUST-CACHE
El tipo de comando Dockerfile sería mucho más flexible. Y para agregar realmente flexibilidad, opcionalmente podría permitir una bandera:
BUST-CACHE $ doit
donde solo se aplica si $ doit está definido, entonces si agregamos soporte para una opción -e en la compilación (https://github.com/docker/docker/pull/9176), la gente podría hacer:
docker build -e doit = ​​true ...

@zamabe Oh, RUN! , lo siento. Aquí estaba usando (!) Para decir "¡Esto es inusual!" sobre la edición de un Dockerfile cada vez que quiero romper el caché en un paso específico. De cualquier manera, podría romper el caché dentro de un Dockerfile antes de que un paso específico sería útil (y para ganar más, si el paso después de ese comando de eliminación de caché es el mismo resultado que el que está en el caché, sea lo suficientemente inteligente como para continuar desde el caché ). BUST-CACHE o ALWAYS RUN (o RUN ALWAYS ) o RUN! ... Realmente cualquier mecanismo que admita esta función, lo usaría.

@duglin ¿Perdón? El título del error dice EJECUTAR, que es más fácil de dar como ejemplo.

@curtiszimmerman ah.

Como un aparte; Creo que la revalidación de caché (?) Está un poco más allá de la invalidación de caché que busca este error. Aunque me gusta lo que está sugiriendo, simplemente reordenaría mi Dockerfile para colocar los comandos de eliminación de caché lo más cerca posible del final. Esto niega los beneficios obtenidos de un _posible_ acceso al caché, ya que _siempre_ haces los cálculos / comparaciones necesarios, lo que probablemente sea una penalización más grave que terminar la compilación de Dockerfile normalmente, ya que las personas que usan la eliminación de caché probablemente esperan / esperan un error de caché.

@zamabe estuvo de acuerdo. Sugiero que si la implementación es bastante trivial para hacer esto, tal vez un comando especial para continuar desde la caché, que está separado del identificador de eliminación de caché. Algo como DISABLE-CACHE en un cierto punto para deshabilitar el caché cada vez, y si tiene un caso de uso en el que el resto del Dockerfile sería costoso en lugar de continuar desde el caché, algo como DISABLE-CACHE? sería continúe desde la caché si es posible. Eso no es una sugerencia, solo una demostración para transmitir de lo que estoy hablando.

+1 para códigos de extracción de git repo

+1

¡Esto sería enorme! En este momento tengo parte de mi integración continua escribiendo el hash de confirmación de git en el Dockerfile (sobrescribiendo un marcador de posición) solo para romper el caché de los clones de git.

Envié este PR: https://github.com/docker/docker/pull/10682 para abordar este problema.
Si bien no admite volver a activar el almacenamiento en caché, no creo que eso sea posible hoy.

+1

Estoy generando un número aleatorio en el Dockerfile y se almacena en caché ...
+1 para una instrucción NOCACHERUN

+1
Debería ser realmente útil para algunos RUN que tenemos que hacer cada vez sin reconstruir todo

Me he dado cuenta de que git clone llegará al caché, pero go get -d no. alguna idea por qué?

_Revisión colectiva con @ LK4D4 @calavera @jfrazelle @crosbymichael @tiborvass_

Cerrando esto, ya que no vemos tantos casos de uso del mundo real (consulte el # 10682 relacionado para obtener más detalles).

+1 para EJECUTAR. Sería bueno.

+1

docker 1.9 introduce variables de tiempo de compilación; es posible (mal) usarlos para forzar la ruptura del caché; para obtener más información, consulte https://github.com/docker/docker/issues/15182

¿Cómo es que esto todavía no es una característica?

@ hacksaw6 Puedes echar un vistazo a lo que se dijo aquí: https://github.com/docker/docker/pull/10682

+1

+1

+1 ¡¿¡¿¡¿¡¿¡cómo esto ni siquiera es una cosa todavía !!! ???!

+1 Necesitamos esta función para proporcionar un control más granular para la construcción.

+1

+1

+1

+1

+1 muy útil
(usando la solución @timruffles por ahora)

+1

+1

+1

Podría ser útil que la gente publique sus casos de uso en lugar de solo +1 para que la gente pueda ver por qué esta es solo una característica necesaria.

+1, llegó aquí a través de Google en busca de una solución para un clon de git almacenado en caché.

Mi caso de uso:
Tengo una configuración de Docker, que durante su compilación llamará a través de gradle a una aplicación de microservicio maravillosa en modo de ejecución en seco. Esto dará como resultado que todas las bibliotecas Java dependientes (desde un repositorio mvn remoto) se descargarán en el repositorio mvn de Docker local. La ejecución en seco simplemente ejecutará la aplicación y regresará inmediatamente, pero asegurará que se carguen todas las dependencias de la biblioteca Java.
Durante la fase de ejecución de la ventana acoplable, la misma aplicación se ejecutará a través de gradle: modo sin conexión. Es decir, la aplicación de microservicio simplemente se cargará desde el directorio del repositorio mvn local. no se llevará a cabo una búsqueda de biblioteca remota costosa y que requiere mucho tiempo. Cuando publique una nueva versión instantánea de dicha biblioteca, la ventana acoplable no activará una búsqueda remota durante una compilación (es decir, no llamará a mi gradle dryrun cmd), a menos que modifique el directorio de la ventana acoplable.

Mi caso de uso: obtenga la última versión de terceros de una biblioteca para usar en una imagen. Estoy usando Docker Hub para eso y AFAIK, no almacenará nada en caché. Pero quién sabe cuándo eso puede cambiar.
Si hubiera un indicador de comando como NOCACHE en la ventana acoplable, lo garantizaría, sin importar dónde se construya la imagen.

Es peor depender de una "característica" del sistema de compilación que de una versión más reciente, en mi humilde opinión.

¿Qué tal agregar una nueva sintaxis: FORCE RUN git clone .... ?

Ahora mismo estoy usando RUN _=$(date) git clone ... para invalidar el caché.

@ c9s, ¿eso realmente funciona? No creo que lo haga.

La variable de entorno de configuración de

@ c9s No veo cómo podría funcionar la configuración de la var env, ya que eso lo hace el shell del contenedor, no el procesamiento de Dockerfile. Cuando intento RUN _=$(date) echo hi , usa el caché en la segunda compilación.

@duglin tienes razón: | no invalida el caché

@ c9s prueba esto en su lugar

FROM foo
ARG CACHE_DATE=2016-01-01
RUN git clone ...
docker build --build-arg CACHE_DATE=$(date) ....

@thaJeztah ¡Gracias! ¡funciona!

+1 clonación de repositorios de git (caso de uso)

Tantos +1, si extrae el repositorio de git en su archivo de docker, el caché evita que sus imágenes se compilen. Hace que sea un poco difícil impulsar compilaciones a través de CI.

+1 clonación de repositorios de git (es muy molesto que la imagen deba construirse desde cero cada vez que se ha realizado una pequeña edición en un repositorio de git)

@Vingtoft Si está actualizando los archivos en el repositorio, su caché se invalidará.

@itsprdp No sabía eso, gracias por aclarar.

@itsprdp Acabo de probar. Cuando actualizo el repositorio y construyo la imagen, Docker todavía está usando el caché.
¿Quizás estoy malinterpretando algo?

@itsprdp Eso no es correcto en mi experiencia. Hice un nuevo compromiso con un repositorio para probar, y cuando se vuelve a compilar, usa el mismo caché.

Si cambio el archivo de la ventana acoplable antes del repositorio, por supuesto, se eliminará la memoria caché, sin embargo, la simple actualización de un repositorio no parece solucionar este problema.

@RyanHartje Perdón por la confusión. Se supone que invalida la caché si el repositorio se actualiza y eso es algo a considerar por los contribuyentes.
El caso de uso que @Vingtoft espera es almacenar en caché el repositorio y solo actualizar los archivos modificados en el repositorio. Esto puede resultar complicado de implementar.

@itsprdp Solo actualizar los archivos modificados en un repositorio sería increíble, pero menos (¿o debería decir más?) también.
En mi caso de uso (y en muchos otros), el git pull real no lleva mucho tiempo: es la construcción de todo lo demás lo que está matando el flujo de desarrollo.

+1, caché utilizado durante la clonación de git :(

Una solución integrada estaría bien, pero mientras tanto puede romper el caché en una instrucción específica de Dockerfile usando ARG .

En el Dockerfile:

ARG CACHEBUST=1
RUN git clone https://github.com/octocat/Hello-World.git

En la línea de comando:

docker build -t your-image --build-arg CACHEBUST=$(date +%s) .

Establecer CACHEBUST a la hora actual significa que siempre será único, y las instrucciones después de la declaración ARG en el Dockerfile no se almacenarán en caché. Tenga en cuenta que también puede compilar sin especificar CACHEBUST build-arg, lo que hará que use el valor predeterminado de 1 y conserve la caché. Esto se puede usar para verificar siempre copias nuevas de repositorios de git, extraer las últimas dependencias de SNAPSHOT, etc.

Editar: Que, eh, es justo lo que dijo @thaJeztah . Dejaré esto como una descripción adicional de su solución.

@ shane-axiom ¿Qué tal si usamos el hash de confirmación de git como valor para CACHEBUST ?

export CACHEBUST=`git ls-remote https://[email protected]/username/myRepo.git | grep refs/heads/develop | cut -f 1` && \
echo $CACHEBUST && \
docker build -t myDockerUser/myDockerImage \
   --build-arg blah=blue \
   --build-arg CACHEBUST=$CACHEBUST \
   .

Basado en pistas de http://stackoverflow.com/questions/15677439/how-to-get-latest-git-commit-hash-command#answer -15679887

@pulkitsinghal Eso se ve maravilloso para reventar el caché de repositorios de git. Para otros usos (como extraer dependencias de SNAPSHOT, etc.), el enfoque de marca de tiempo siempre activa funciona bien.

+1 para CACHE ON | APAGADO

+1

+1

Recuerde el enfoque de ADD https://www.random.org/strings/?num=16&len=16&digits=on&upperalpha=on&loweralpha=on&unique=on&format=plain&rnd=new uuid como solución para los problemas de caché.

Para publicar un caso de uso adicional ...

COPY package.json /usr/src/
RUN npm install

En nuestro package.json , comúnmente apuntaremos a una etiqueta master para algunas de nuestras dependencias privadas de github. Esto significa que nunca obtendremos el último master menos que cambiemos el archivo package.json (por lo general, solo agregue a la descripción un - a la descripción y luego elimínelo durante la prueba).

Un RUN NO CACHE en lugar de RUN parece que sería una buena solución.

+1

Tengo un problema similar para la instalación de npm que usa caché y no usa mi nueva biblioteca publicada en npm.

Sería genial si pudiera deshabilitar la caché por comando EJECUTAR en el archivo de la ventana acoplable.

@brycereynolds @mmobini ver https://github.com/docker/docker/issues/1996#issuecomment -172606763 para romper manualmente la caché. Sin embargo, _no_ especificar una versión específica de los paquetes que deben instalarse puede no ser la mejor práctica, ya que ya no se garantiza que el resultado final de su Dockerfile (y código fuente) sea reproducible (es decir, se compila con éxito hoy en día, pero no lo hace). mañana, porque uno de los paquetes se actualizó). Puedo ver que esto está "bien" durante el desarrollo, pero para la producción (y las compilaciones automatizadas en Docker Hub), el mejor enfoque es especificar explícitamente una versión. Hacerlo también permite a los usuarios verificar los paquetes exactos que se utilizaron para producir la imagen.

Tengo un caso de uso en el que no poder invalidar el caché está causando problemas. Estoy ejecutando aplicaciones Dropwizard (Java REST Services construidos con Maven) de Docker y un sistema automatizado está haciendo todas las compilaciones e implementaciones de contenedores por mí. Incluyo un Dockerfile en mi repositorio y hace el resto. El sistema ejecuta una versión de producción y una o más versiones de desarrollo de mi aplicación. Las compilaciones de desarrollo son donde tengo problemas.

Durante el desarrollo, algunas de las dependencias del proyecto tienen SNAPSHOT en sus números de versión. Esto le indica a Maven que la versión está en desarrollo y que debería traer una nueva versión con cada compilación. Como resultado, una estructura de archivo idéntica puede resultar en dos compilaciones distintas. Este es el comportamiento deseado, ya que los errores pueden haberse solucionado en una dependencia SNAPSHOT. Para respaldar esto, sería útil forzar a Docker a ejecutar un comando en particular, ya que no hay forma de determinar el efecto del comando en función del estado actual del sistema de archivos. La mayoría de los proyectos Java se encontrarán con esto, ya que las dependencias SNAPSHOT de estilo Maven son utilizadas por varios sistemas de compilación diferentes.

@ctrimble Puede usar --no-cache , o --build-arg para invalidar la caché.
Puede minimizar el efecto de --no-cache al tener una imagen base con todos los comandos que se pueden almacenar en caché.

@ cpuguy83 gracias por la respuesta. Leo el hilo y entiendo las opciones actuales. Abrí un ticket con el sistema de compilación que estoy usando para proporcionar un argumento de prevención de caché. Producir dos imágenes distintas para una sola aplicación parece ser un montón de obstáculos para acelerar las compilaciones. Sería mucho más fácil poder especificar algo como:

  1. hacer cosas que se pueden almacenar en caché si el sistema de archivos es idéntico
  2. hacer algo que pueda cambiar el sistema de archivos en función de cuándo se ejecuta
  3. hacer algunas cosas más que podrían almacenarse en caché si el paso anterior no cambió el sistema de archivos

Este patrón aparecerá con frecuencia en las compilaciones de desarrollo. Sería bueno tener una semántica en el Dockerfile.

@ctrimble La destrucción de la memoria caché en un paso hará que la memoria caché siempre se destruya para cada paso posterior.

@ cpuguy83 exactamente. La semántica de mi sistema de compilación es temporal para las compilaciones de desarrollo. Tengo que seleccionar las compilaciones correctas sobre el almacenamiento en caché. Realmente me gustaría conseguir ambos.

Ha habido una discusión considerable aquí, disculpas si ya se ha sugerido, pero ¿y si hubiera algo como esto?

CHECK [FILE_PATH]

Todo lo que haría Docker es almacenar el MD5 (o cualquier otro hash que esté de moda) del archivo y, si cambia, todos los pasos posteriores se invalidan.

Probablemente estaría haciendo algo como:

CHECK Gemfile
CHECK package.json
CHECK composter.json
CHECK project.json

También es posible que desee habilitar una verificación de que de alguna manera transcurre después de un período de tiempo. El parámetro cache_valid_time Ansible para el complemento apt puede ofrecer algo de inspiración: http://docs.ansible.com/ansible/apt_module.html

Para eso, la sintaxis sería:

EXPIRE 1234567 
RUN apt-get update
RUN bundle install

Docker sabría el tiempo de la última ejecución y calcularía si el tiempo había transcurrido basándose en "ahora".

@atrauzzi Solo --squash en la compilación ahora en 1.13 (experimental solo por ahora).

@ cpuguy83 ¿Hay algún documento o explicación sobre --squash algún lugar que pueda leer? Al principio, el nombre no hace que parezca que hace lo que estoy pensando. ¡Pero podría estar (y probablemente lo esté) equivocado!

@atrauzzi sí, en la referencia de compilación.

Básicamente, --squash conserva la caché de la capa y crea una segunda imagen que es como si todo en el Dockerfile sucediera en una sola capa.

No veo por qué uno necesitaría verificar que un caché de archivos todavía sea válido individualmente, ADD y COPY ya hacen esto para todo lo que se está copiando.

@ cpuguy83 Buen punto, ni siquiera lo pensé y, por supuesto, ya lo estoy usando.

¿Qué pasa con el enfoque de marca de tiempo / duración? ¿Es eso factible con lo que ya está disponible?

¿Qué pasa con el enfoque de marca de tiempo / duración? ¿Es eso factible con lo que ya está disponible?

A través de build-args;

ARG expire_after=never
RUN do some thing
docker build --build-arg expire_after=2016-12-01 -t foo .

cambiar el argumento de compilación para romper el caché

+1 para una forma más limpia

+1 para una forma más limpia

También debería haber opciones separadas para deshabilitar la lectura de la caché y para deshabilitar la escritura en ella. Por ejemplo, es posible que desee crear una imagen nueva desde cero e ignorar las capas almacenadas en caché, pero aún así escribir las nuevas capas resultantes en la caché.

+1

¿Puedo sugerir pasar el número de paso al comando de compilación?

Algo como esto:
docker build --step 5 .

Ignoraría todos los cachés después del paso 5 incluido durante la compilación.

+1
Por favor.

CACHE ENCENDIDO | APAGADO +1

El problema con estos comandos CACHE ON|OFF es que en cualquier paso que se desactive la caché, no hay forma de almacenar en caché los pasos adicionales. El único comando sensato sería ENDCACHE .

Es una idea / ética válida. Se supone que el comando fusiona todas las capas no almacenadas en caché en una sola capa en el momento en que la caché se vuelve a activar. Por supuesto, aún puede argumentar la mejor nomenclatura / corrección de la semántica / sintaxis preferida de la función.

+1

+1 la característica imprescindible

Aceptar CACHE ON | OFF +1

+1 Sería increíble.

Realmente no entendía la forma en que Docker almacena en caché los pasos antes y pasé medio día investigando por qué mi sistema no se está construyendo correctamente. Fue el almacenamiento en caché "git clone".

Me encantaría tener la palabra clave ALWAYS .

Como esta cerrado

¿Cuál es la mejor solución?

Probé https://github.com/moby/moby/issues/1996#issuecomment -185872769 y funcionó
En el Dockerfile:

ARG CACHEBUST=1
RUN git clone https://github.com/octocat/Hello-World.git

En la línea de comando:

docker build -t your-image --build-arg CACHEBUST=$(date +%s)

¿Por qué no crear un nuevo comando similar a RUN pero que nunca almacena en caché RUNNC para RUN NO CACHE?

Puedo confirmar, @habeebr (https://github.com/moby/moby/issues/1996#issuecomment-295683518) - Lo uso en combinación con https://github.com/moby/moby/issues/1996# problema comentario -191543335

+1

¡RUNNC es una gran idea!

¿Por qué se cerró este problema? Entre la miríada de duplicados que solicitan esencialmente lo mismo y el extenso historial de comentarios de más de uno de estos duplicados, parece _obvio que existe un interés saludable en ver esta funcionalidad disponible.

Entiendo que es difícil, y quizás nadie ha sugerido una solución lo suficientemente elegante que satisfaga la necesidad y sea lo suficientemente limpia para ser una adición atractiva de Docker ... pero eso no significa _que no sea necesario_.

El único otro argumento que he escuchado a favor de cerrar esto es que hay otras formas de lograrlo ... pero ese argumento tampoco es válido. Crear múltiples imágenes base con el único propósito de sortear la falta de control de caché es difícil de manejar, idear una invalidación a través de un ARG es obtuso y poco intuitivo. Me imagino que los usuarios quieren utilizar estas "soluciones" tanto como los desarrolladores de Docker quieren incorporar oficialmente un truco descuidado en la herramienta.

no es difícil: https://github.com/moby/moby/pull/10682
solución fácil, UX fácil. Simplemente no hay un consenso claro sobre si debe hacerse.

Wow solo wow...

Ya lo habría implementado solo para no tener que escucharlo, sin importar que haya un consenso claro de que la base de usuarios lo quiere. No he estado en el lado del desarrollador de un proyecto de código abierto tan grande, solo en proyectos mucho más pequeños, así que tal vez me esté perdiendo algo.

+1

+1 para una seguridad sensata y un mejor rendimiento

+1

+1

+1

+1

+1

+1

¿Pueden dejar de enviar spam al +1? Solo usa la función de reacción para votar a favor.

¿Algún cambio?
Aún no sabe por qué se cierra este problema.
En mi opinión, es una característica imprescindible que maneja perfectamente la extracción de versiones desde el repositorio remoto de git.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

¿Por qué cerrar esto? Creo que es útil

+1

+1

+1

Actualmente, la forma más sencilla de deshabilitar el caché para una capa (y lo siguiente):

Dockerfile

ARG CACHE_DATE
RUN wget https://raw.githubusercontent.com/want/lastest-file/master/install.sh -O - | bash

Y cuando creas la imagen, --build-arg debe agregarse

docker build  --build-arg CACHE_DATE="$(date)"

Luego, el comando wget se ejecutará cada vez que cree la imagen, en lugar de usar un caché.

RUNNC o CACHE OFF sería bueno

Mientras tanto, esto parece prometedor:
http://dev.im-bot.com/docker-select-caching/

es decir:

screenshot 2018-05-26 19 03 09

Voy a mantener la calma y unirme a la manada:

+1

Sí, necesito almacenamiento en caché selectivo de los comandos. Mi COPY falla el 80% del tiempo si solo cambio una palabra en un archivo de configuración. Me gustaría nunca almacenar en caché mi COPY sino almacenar en caché todo lo demás. Tener CACHE ON y CACHE OFF sería genial.

RUN X
RUN X
CACHE OFF
COPY /config /etc/myapp/config
CACHE ON

@shadycuz Nunca podrá "volver a habilitar" el caché después de deshabilitarlo / invalidarlo usando cualquier método. La compilación no podrá verificar (en un período de tiempo razonable con una cantidad razonable de recursos) que la capa no almacenada en caché no cambió algo más en el sistema de archivos que debería considerar en capas más nuevas. Para minimizar el impacto de tener siempre la necesidad de extraer un archivo de configuración externo, debe colocar su directiva COPY tan abajo como sea posible en el Dockerfile (para que Docker pueda usar el caché de compilación para la mayor parte del proceso de compilación posible antes de que se invalide el caché).

Para invalidar la caché en un punto específico del proceso de compilación, puede consultar cualquiera de los otros comentarios sobre el uso de --build-arg y ARG mencionados aquí anteriormente.

@shadycuz @curtiszimmerman Sí, solo podemos conservar CACHE OFF pero no CACHE ON , porque las siguientes capas deben reconstruirse si se cambia una capa anterior.

Estoy de acuerdo en que CACHE ON no tiene sentido desde un punto de vista técnico. Ayuda a expresar la intención con más claridad, sin embargo, qué capas están destinadas a invalidarse.

Una solución más flexible sería un comando similar a RUN que permitiera que algún código de shell determinara si la caché debería invalidarse. Un código de salida de 0 podría significar "usar caché" y 1 "invalidar caché". Si no se proporciona un código de shell, el valor predeterminado podría ser invalidar el caché de aquí en adelante. El comando podría llamarse INVALIDATE, por ejemplo.

¿Por qué se cerró esto sin comentarios?

Hubo un comentario, pero está oculto por github.
https://github.com/moby/moby/issues/1996#issuecomment -93592837

+1

Esta función me salvaría la vida en este momento.

+1

Cerrando esto porque no vemos tantos casos de uso del mundo real

212 comentarios y contando, pero ¿todavía no hay caso de uso? Parece bastante ignorante.

+1

+1

+1

+1

+1

el problema todavía está aquí y todavía requiere una solución. Todavía existen muchos usos en el mundo real.

+1

Sospecho que los desarrolladores de Docker no tienen ningún incentivo para implementar esto, para proteger su infraestructura de edificio centralizada de ser DDsS por solicitudes sin caché.

También sospecho que una infraestructura paralela que facilite las compilaciones sin caché sería interesante para los usuarios empresariales.

En general, este problema no se trata de una función de software, sino de un problema de escala del servicio.

@jaromil Eso no es del todo cierto, ya que esto tampoco es posible en repositorios

¿Qué software existe para ejecutar un repositorio autohospedado? Realmente no sé a qué te refieres.
Una solución autohospedada simple podría ser una clonación cron de repositorios git y ejecutar una compilación de docker --no-cache - Estoy seguro de que este problema no puede ocurrir en el software de código abierto: cualquiera puede modificar la línea de comandos de compilación de la ventana acoplable.

@jaromil No creo que ese sea el problema. Sería más eficiente tenerlo para los proyectos de código abierto de DockerHub (además de los pagos, no cobran por la cantidad de compilaciones). En un entorno de CI / CD con compilaciones frecuentes, esto empeora aún más.

Siempre que necesite hacer eso (está usando docker y git y no quiere tener 5 contenedores que ejecutan volúmenes compartidos), debe reconstruir el contenedor y cargarlo cada vez que cargue una nueva versión. Todo el contenedor.
Con un indicador sin caché en el código, cada vez que ejecuta la compilación, simplemente crea y reemplaza esa capa única en lugar del contenedor completo para actualizar la versión.

Sobre el representante de autohospedaje, se sorprendería. Entiendo el comentario de @bluzi , no hay impacto de ddos ​​si se auto-hospeda (o usa aws ecr).

Ok, este es sin duda un escenario más complejo que estaba imaginando. ahora creo que ... cargando con una especie de hashes de capa única sin caché ... empujar y anular, lo que sea. No estoy seguro

TLDR: Creo que algunas mejoras en la documentación de Docker podrían ayudar mucho.

Terminé aquí después de encontrar mis propios problemas / confusión con el almacenamiento en caché. Después de leer todos los comentarios aquí y en https://github.com/moby/moby/pull/10682, encontré una solución viable para mi caso de uso particular. Sin embargo, de alguna manera todavía me sentía frustrado con la respuesta de Docker a esto, y parece que muchos otros sienten lo mismo.

¿Por qué? Después de pensar en esto desde varios ángulos diferentes, creo que el problema aquí es una combinación de casos de uso vagos, argumentos demasiado generalizados contra los cambios propuestos (que pueden ser válidos pero no abordan directamente los casos de uso presentados) y la falta de documentación para las recomendaciones de Docker para algunos casos de uso comunes. Quizás pueda ayudar a aclarar las cosas e identificar la documentación que podría mejorarse para ayudar con esta situación.

Leyendo entre líneas, me parece que la mayoría de los primeros comentaristas en esta solicitud de función estarían contentos con una solución que usa argumentos adicionales a docker image build para deshabilitar el caché en un punto específico en el Dockerfile. Parece que la solución actual de Docker para esto (descrita en https://github.com/moby/moby/issues/1996#issuecomment-172606763) debería ser suficiente en la mayoría de estos casos, y parece que muchos usuarios están contentos con esto . (Si alguien tiene un caso de uso en el que puede proporcionar argumentos adicionales a docker image build pero esta solución aún es inadecuada, probablemente sería útil agregar un comentario que explique por qué esto es inadecuado).

Toda la frustración persistente parece estar relacionada con el requisito de pasar argumentos adicionales a docker image build para controlar el comportamiento de almacenamiento en caché. Sin embargo, los casos de uso relacionados con esto no se han descrito muy bien.

Al leer entre líneas nuevamente, me parece que todos estos casos de uso están relacionados con servicios que ejecutan docker image build en nombre de un usuario, o relacionados con Dockerfiles que se distribuyen a otros usuarios que luego ejecutan docker image build ellos mismos. (Si alguien tiene otros casos de uso en los que pasar argumentos adicionales a docker image build es un problema, probablemente sería útil agregar un comentario que explique su caso de uso en detalle).

En muchos de estos casos, parece que el caso de uso en realidad no requiere la capacidad de deshabilitar el almacenamiento en caché en un punto específico del Dockerfile (que era el punto original de esta solicitud de función). En cambio, parece que muchos usuarios estarían contentos con la capacidad de deshabilitar el almacenamiento en caché por completo desde el Dockerfile, sin usar el argumento "--no-cache" en docker image build y sin requerir modificaciones manuales al Dockerfile antes de cada construir. (Al describir los casos de uso, probablemente sería útil mencionar si el almacenamiento en caché parcial es realmente necesario o si deshabilitar el caché por completo sería suficiente para su caso de uso).

En los casos en que un servicio ejecuta docker image build en nombre de un usuario, parece que Docker espera que todos esos servicios deshabiliten incondicionalmente el caché o le den al usuario la opción de deshabilitar el caché. Según https://github.com/moby/moby/pull/10682#issuecomment-73777822, Docker Hub deshabilita incondicionalmente el caché. Si un servicio aún no hace esto, Docker ha sugerido https://github.com/moby/moby/pull/10682#issuecomment-159255451 quejarse al proveedor de servicios al respecto.

Me parece que esta es una posición razonable para Docker con respecto a los servicios que ejecutan docker image build . Sin embargo, esta posición realmente debe documentarse oficialmente en un lugar visible para que tanto los proveedores de servicios como los usuarios sepan qué esperar. No parece que esta posición o el comportamiento de almacenamiento en caché de Docker Hub estén actualmente documentados en otro lugar que no sean los comentarios improvisados ​​enterrados en lo más profundo de esa solicitud de extracción enorme / antigua / cerrada, por lo que no es de extrañar que tanto los proveedores de servicios como los usuarios de forma rutinaria hacer esto mal. ¿Quizás agregar información a la referencia docker build describe la opinión de Docker sobre el uso del almacenamiento en caché por parte de los servicios de compilación y agregar información a la documentación de compilación automatizada de Docker Hub sobre el comportamiento de almacenamiento en caché de Docker Hub podría eliminar este problema?

Para los casos en los que Dockerfiles se distribuyen a otros usuarios que luego ejecutan docker image build ellos mismos, algunas personas han argumentado que el uso del comando docker build . simple (sin argumentos adicionales) es tan común que sería No es razonable que los constructores de Dockerfile requieran que los usuarios agreguen argumentos, mientras que otras personas (por ejemplo: https://github.com/moby/moby/issues/1996#issuecomment-72238673 https://github.com/moby/moby/pull / 10682 # issuecomment-73820913 https://github.com/moby/moby/pull/10682#issuecomment-73992301) han argumentado que sería inapropiado evitar incondicionalmente que los usuarios usen el almacenamiento en caché mediante la codificación rígida de anulaciones de caché en Dockerfile. En ausencia de casos de uso detallados / convincentes para esto, Docker ha tomado la decisión ejecutiva de requerir argumentos de línea de comando adicionales para controlar el almacenamiento en caché, que parece ser la fuente de gran parte de la frustración persistente. (Si alguien tiene un caso de uso convincente relacionado con esto, probablemente sería útil agregar un comentario que lo explique en detalle).

Sin embargo, me parece que Docker puede hacer felices a todos simplemente rompiendo el hábito de los usuarios de ejecutar docker build . sin argumentos adicionales. El comportamiento de almacenamiento en caché y el argumento "--no-cache" no se mencionan en ninguno de los tutoriales de Docker relevantes (como este o este
o esto ). Además, aunque la documentación docker build enumera el argumento "--no-cache", no explica su significado ni resalta el hecho de que es importante en muchos casos de uso comunes. (Tenga en cuenta también que la documentación de docker image build está vacía. Debería al menos hacer referencia a la documentación de docker build ). Parece que solo la referencia de Dockerfile y la documentación de mejores prácticas realmente describen el comportamiento de almacenamiento en caché y mencionan el rol del argumento "--no-cache". Sin embargo, es probable que estos documentos solo sean leídos por escritores avanzados de Dockerfile. Por lo tanto, no es de extrañar que solo los usuarios avanzados estén familiarizados con el argumento "--no-cache", y que la mayoría de los usuarios solo ejecuten docker build . sin argumentos adicionales y luego se confundan cuando no se comporta cómo ellos o el escritor de Dockerfile esperan / quieren. ¿Quizás actualizar los tutoriales y la documentación de docker build para mencionar el argumento "--no-cache" y su importancia podría eliminar este problema?

+1

+1

La herramienta oficial de Docker ,

+1

+1

El caso de uso que estoy abordando en este momento es querer pasar secretos transitorios y de corta duración como argumentos de compilación para instalar paquetes privados. Eso rompe completamente el almacenamiento en caché porque significa que cada vez que cambia el secreto (básicamente cada compilación), el caché se rompe y los paquetes se reinstalan de nuevo, aunque el único cambio es el secreto.

Intenté omitir esto consumiendo ARG en un script que se copia antes de especificar ARG, pero Docker parece invalidar todo después de que se declara ARG si la entrada ARG ha cambiado.

El comportamiento que me gustaría ver es poder marcar un ARG como siempre en caché, ya sea en el Dockerfile o en la CLI al llamar a build. Para casos de uso como secretos, eso es a menudo lo que desea; el contenido de la lista de paquetes debe dictar cuándo se invalida la caché, no el argumento pasado a ARG.

Entiendo la teoría de que estas secciones podrían extraerse en una segunda imagen que luego se usará como imagen base, pero eso es bastante incómodo cuando los paquetes son usados ​​por un proyecto, como en un package.json, requirements.txt, Gemfile, etc. Esa imagen base también se reconstruirá continuamente.

+1 a CACHE OFF de esta directiva de línea: he estado esperando esto literalmente durante años.

Tuve que deshabilitar el caché en el concentrador de la ventana acoplable / la nube de la ventana acoplable y esto ahorraría toneladas de tiempo y compilaciones si pudiera almacenar en caché la capa grande y luego ejecutar un comando de actualización nocache cerca del final del archivo docker.

El comportamiento que me gustaría ver es poder marcar un ARG como siempre en caché, ya sea en el Dockerfile o en la CLI al llamar a build. Para casos de uso como secretos, eso es a menudo lo que desea; el contenido de la lista de paquetes debe dictar cuándo se invalida la caché, no el argumento pasado a ARG.

--build-arg PASSWORD=<wrong> podría producir un resultado diferente al de --build-arg PASSWORD=<correct> , por lo que no estoy seguro de si solo mirar el contenido de la lista de paquetes funcionaría para eso. El constructor no puede anticipar por sí mismo qué efecto tendría la configuración / cambio de una variable de entorno en los pasos que se ejecutan (¿son make DEBUG=1 foo y make DEBUG=0 foo iguales?). La única excepción que se hace actualmente es para las variables de entorno xx_PROXY , donde se asume que puede ser necesario un proxy para las conexiones de red, pero cambiar a un proxy diferente debería producir el mismo resultado. Entonces, para que eso funcione, se necesitaría alguna forma de indicar una variable de entorno específica (/ build arg) que se ignorará para el almacenamiento en caché.

Tenga en cuenta que BuildKit ahora tiene soporte experimental para RUN --mount=type=secret y RUN --mount=type=ssh , lo que puede ser útil para pasar secretos / credenciales, pero aún puede invalidar el caché si esos secretos cambian (no estoy seguro; esto podría ser algo para aparecer en el rastreador de problemas de buildkit https://github.com/moby/buildkit/issues).

Tuve que deshabilitar el caché en Docker Hub / Docker Cloud

¿Docker Hub / Cloud realmente _utiliza_ el almacenamiento en caché? Creo que no se usa almacenamiento en caché allí (como en; está usando entornos de compilación efímeros)

Recuerdo que DockerHub solía no usar el almacenamiento en caché de compilación, pero había estado mirando mis compilaciones automatizadas en Docker Cloud justo antes de este ticket y ahora hay un control deslizante de Almacenamiento en caché de construcción al lado del control deslizante Autobuild de cada rama, aunque está desactivado de forma predeterminada.

No me atrevo a habilitar el almacenamiento en caché de compilación porque pasos como git clone no obtendrán la última descarga del repositorio, ya que solo compara la cadena de directiva que no cambiará. Al explicarle este problema a un colega hoy que ha sido una espina clavada en nuestro costado durante años, se sorprendió, ya que parece una gran imperfección para muchos casos de uso.

Preferiría con mucho que el git clone && make build inicial se almacene en caché y luego haga un NO CACHE en un paso git pull && make build para obtener solo una actualización de código mucho más pequeña + dependencias que aún no estén instaladas como la última capa, por lo tanto almacenando en caché de manera eficiente la mayor parte de la imagen, no solo para compilaciones, sino más importante aún para todos los clientes que ahora deben volver a descargar y reemplazar cientos de MB de capas cada vez, lo cual es extremadamente ineficiente.

El tamaño se debe a que muchos de los proyectos tienen una gran cantidad de dependencias, por ejemplo. paquetes de sistema + módulos Perl CPAN + módulos Python PyPI, etc.

Incluso el uso de Alpine no es mucho más pequeño una vez que agrega las dependencias del paquete del sistema y las dependencias de CPAN y PyPI, ya que he estado usando Alpine durante años para intentar ver si podía crear imágenes más pequeñas, pero una vez que tiene muchas dependencias, no es así. hace una gran diferencia si la base comienza más pequeña, ya que al agregar paquetes del sistema, se agrega la mayor parte de inmediato.

Almacenar en caché las capas anteriores que incluyen todos los paquetes del sistema + módulos CPAN + PyPI significaría que muy poco debería terminar cambiando en la última capa de actualizaciones, ya que no actualizaré los módulos instalados que funcionan en la mayoría de los casos (usé scripts de mis herramientas bash repositorio de submódulo de utilidad para instalar solo paquetes que aún no están instalados para evitar la instalación de actualizaciones innecesarias sin corrección de errores)

Estuve buscando usar un truco como cambiar ARG por un tiempo (una idea que obtuve al buscar en blogs como http://dev.im-bot.com/docker-select-caching/):

En Dockerfile:

ARG NOCACHE=0

Luego ejecute docker build así:

docker build --build-arg NOCACHE=$(date +%s) ...

pero no creo que esto sea posible en Docker Cloud.

Hay variables de entorno, pero parece que no es posible usar contenido dinámico como epoch anterior (o al menos no documentado que pude encontrar), y con las variables de entorno no estoy seguro de que invalide el almacenamiento en caché para esa línea directiva en adelante.

@thaJeztah Sí, este tipo de comportamiento fácilmente podría tener consecuencias negativas si se malinterpreta o se abusa, pero resolvería muy bien ciertos casos de uso.

--build-arg PASSWORD=<wrong> podría producir un resultado diferente a --build-arg PASSWORD=<correct> , por lo que no estoy seguro de si solo mirar el contenido de la lista de paquetes funcionaría para eso

Aunque tiene razón en que produciría resultados diferentes, si la lista de paquetes no ha cambiado, realmente no me importa si la contraseña es correcta o incorrecta; los paquetes ya están en la imagen anterior, por lo que el usuario que ejecuta esto ya tiene acceso (es decir, no es un problema de seguridad), y si la contraseña era incorrecta anteriormente, esperaría que la carga recaiga en el autor de Dockerfile para fallar en la instalación si es necesario, lo que significa que aún tendrá la oportunidad de instalar correctamente los paquetes después de corregir la contraseña.

Sí, me estaba imaginando algo como docker build --force-cache-build-arg SECRET=supersecret . Eso es bastante torpe, estoy seguro de que alguien podría pensar en algo mejor.

@HariSekhon Parece que su caso de uso es en realidad el opuesto al mío, ¿verdad? Usted quiere perder la fuerza de forma selectiva la caché, en lugar de la fuerza selectiva golpeó el caché?

Agregar esto funcionó para mí:

ADD http://date.jsontest.com/ /tmp/bustcache

pero ese sitio está caído en este momento. Esto debería funcionar

ADD http://api.geonames.org/timezoneJSON?formatted=true&lat=47.01&lng=10.2&username=demo&style=full /tmp/bustcache

@itdependsnetworks

Perfecto, es una buena solución y el sitio está actualizado ahora. También es útil registrar la fecha de construcción de la imagen.

Había probado esto y otros archivos especiales similares deberían cambiar cada vez

COPY /dev/random ...

pero eso no funcionó a pesar de que RUN ls -l -R /etc mostró que tales archivos estaban presentes y no siempre se encontraron, sospecho que hay alguna protección contra el uso de archivos especiales.

Ahora lo pienso más en DockerHub / Docker Cloud, probablemente también podría usar un gancho de compilación previa para generar un archivo que contenga una marca de fecha y luego COPIAR eso en la imagen justo antes de la capa que desea almacenar en caché, logrando un resultado similar, aunque el ADD Como se muestra arriba, creo que es más portátil para las compilaciones de Docker local y en la nube.

Necesitamos encontrar un sitio de impresión de fecha más confiable para esta solución alternativa de eliminación de caché; los dos anteriores parecen ser demostraciones / tienen cuotas y, por lo tanto, no son confiables y rompen compilaciones al azar.

El primero rompe su cuota diaria todo el tiempo y el segundo ahora da este error

{"status": {
  "message": "the daily limit of 20000 credits for demo has been exceeded. Please use an application specific account. Do not use the demo account for your application.",
  "value": 18
}}

Creo que sería genial tener una instrucción que pueda poner en un archivo de la ventana acoplable que se ejecutará en cada compilación y, si la salida difiere de la última compilación, se reconstruirán las capas posteriores.

El uso de ejemplo sería:

FROM something
... 
CACHE_BUST git ls-remote my-git-repo HEAD
RUN git clone --depth=1 my-git-repo ...
...
CMD ["my-cmd"]

El comando en la instrucción CACHE_BUST anterior generará el SHA del HEAD del repositorio especificado, de esta manera mi dockerfile puede saber si clonar o no en función de los cambios en el repositorio.

Todos mis casos de uso aquí están relacionados con capas relacionadas con la red no deterministas como se ve arriba. Actualmente puedo usar ARG para todas mis necesidades aquí, pero eso significa que a menudo necesito un script de compilación que use un archivo docker, cuando sería bueno tener solo el archivo docker para mantenerlo. (además, algunas herramientas no permiten argumentos)

Mi flujo de trabajo actual se vería así:

ARG SHA_TO_BUILD
RUN echo SHA_TO_BUILD
RUN git clone ...
...everything else reliant on that clone
$> ./build-my-image.sh $(get-latest-sha)

Creo que activar y desactivar el almacenamiento en caché para cada comando es una mala idea, los archivos deben escribirse de tal manera que si una capa necesita reconstruirse, el resto también. Pero creo que sería bueno poder forzar una reconstrucción en un punto determinado del archivo.

una característica tan buena, ¿por qué todavía está pendiente?

Otro caso de uso es cuando el contenido de un archivo cambia pero Dockerfile no.

Por ejemplo, si tengo un COPY file.txt . y modifico file.txt Docker seguirá usando la versión anterior almacenada en caché.

Si Docker realizara una suma de comprobación de los archivos que copió y usó la próxima vez para determinar si debería usar la capa en caché que resolvería el problema.

A partir de ahora me veo obligado a usar --no-cache y eso descarga y funciona mucho más de lo necesario (desperdiciando tiempo y ancho de banda).

@brennancheung si ese es el caso, es un error. No dude en abrir una edición separada con pasos reproducibles.

Creo que el punto principal de lo que @brennancheung
https://github.com/brennancheung está diciendo es, por ejemplo, cuando estás
cargando un archivo de configuración (o algo similar). No es necesario
reinstale la aplicación completa, solo actualice estos archivos y los comandos
asociado con él, ejecute la ventana acoplable y listo, el sistema está configurado.
Por supuesto, a menudo puede poner el archivo de configuración más cerca del final de
su pila, pero ese no es siempre el caso.

Am Mi., 20. Marz 2019 um 00:10 Uhr schrieb Tibor Vass <
[email protected]>:

@brennancheung https://github.com/brennancheung si ese es el caso,
es un error. No dude en abrir una edición separada con pasos reproducibles.

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

-
Thiago Rodrigues

Probé esto https://github.com/moby/moby/issues/1996#issuecomment -185872769

Pero solo afecta al caché en / después del primer uso y no solo a su definición.

https://docs.docker.com/engine/reference/builder/#impact -on-build-caching

Si un Dockerfile define una variable ARG cuyo valor es diferente de una compilación anterior, entonces se produce un "error de caché" en su primer uso, no en su definición.

@samstav "primer uso" hay el primer RUN después del ARG (si ese ARG es con una etapa de construcción), entonces:

ARG FOO=bar

FROM something
RUN echo "this won't be affected if the value of FOO changes"
ARG FOO
RUN echo "this step will be executed again if the value of FOO changes"

FROM something-else
RUN echo "this won't be affected because this stage doesn't use the FOO build-arg"

Lo anterior depende un poco si está utilizando el constructor de próxima generación (BuildKit), por lo que con DOCKER_BUILDKIT=1 habilitado, porque BuildKit puede omitir etapas de construcción si no son necesarias para la etapa final (o omitir etapas de construcción si se pueden almacenar en caché por completo)

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