Cómo forzar a Docker para una construcción limpia de una imagen

819

He creado una imagen Docker a partir de un archivo Docker usando el siguiente comando.

$ docker build -t u12_core -f u12_core .

Cuando intento reconstruirlo con el mismo comando, está usando el caché de compilación como:

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <[email protected]>
 ---> Using cache
 ---> 4354ccf9dcd8
Step 3 : RUN apt-get update
 ---> Using cache
 ---> bcbca2fcf204
Step 4 : RUN apt-get install -y openjdk-7-jdk
 ---> Using cache
 ---> 103f1a261d44
Step 5 : RUN apt-get install -y openssh-server
 ---> Using cache
 ---> dde41f8d0904
Step 6 : RUN apt-get install -y git-core
 ---> Using cache
 ---> 9be002f08b6a
Step 7 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> a752fd73a698
Step 8 : RUN apt-get install -y logrotate
 ---> Using cache
 ---> 93bca09b509d
Step 9 : RUN apt-get install -y lsb-release
 ---> Using cache
 ---> fd4d10cf18bc
Step 10 : RUN mkdir /var/run/sshd
 ---> Using cache
 ---> 63b4ecc39ff0
Step 11 : RUN echo 'root:root' | chpasswd
 ---> Using cache
 ---> 9532e31518a6
Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
 ---> Using cache
 ---> 47d1660bd544
Step 13 : RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
 ---> Using cache
 ---> d1f97f1c52f7
Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'
 ---> Using cache
 ---> bd7dde7a98b9
Step 15 : RUN tar -xvf aerospike.tgz
 ---> Using cache
 ---> 54adaa09921f
Step 16 : RUN dpkg -i aerospike-server-community-*/*.deb
 ---> Using cache
 ---> 11aba013eea5
Step 17 : EXPOSE 22 3000 3001 3002 3003
 ---> Using cache
 ---> e33aaa78a931
Step 18 : CMD /usr/sbin/sshd -D
 ---> Using cache
 ---> 25f5fe70fa84
Successfully built 25f5fe70fa84

El caché muestra que está instalado aerospike. Sin embargo, no lo encuentro dentro de los contenedores generados a partir de esta imagen, por lo que quiero reconstruir esta imagen sin usar el caché. ¿Cómo puedo forzar a Docker a reconstruir una imagen limpia sin el caché?

Pavan Gupta
fuente
10
Como comentario aparte, generalmente debe intentar minimizar el número de RUNdirectivas.
tripleee
44
@tripleee ¿Puedes explicar por qué?
Ya
99
@Ya. Solía ​​ser que Docker siempre creaba una capa separada para cada RUNdirectiva, por lo que una Dockerfilecon muchas RUNdirectivas consumiría enormes cantidades de espacio en disco; pero esto aparentemente ha mejorado algo en las versiones recientes.
tripleee
Cuando lo intento docker-compose up -d, ¿dónde puedo usar --no-cache?
Oo
1
@Oo eso no es posible. Primero tienes que hacer docker-compose build --no-cachey luegodocker-compose up -d
Martin Melka

Respuestas:

1446

Hay una --no-cacheopción:

docker build --no-cache -t u12_core -f u12_core .

En versiones anteriores de Docker necesitabas pasar --no-cache=true, pero este ya no es el caso.

Assaf Lavie
fuente
89
También tenga en cuenta que --no-cachefunciona con docker-compose build.
Blackus
42
También es posible que desee usar --pull. Esto le indicará a Docker que obtenga la última versión de la imagen base. Esto es necesario además de --no-cachesi ya tiene la imagen base (ej . ubuntu/latest:) y la imagen base se ha actualizado desde la última vez que la sacó. Ver los documentos aquí .
Collin Krawll
2
@CollinKrawll: La --pullopción me sirvió. Simplemente --no-cache, la construcción aún se rompió. Poner --pulltambién, construir trabajado! ¡Gracias!
Erdős-Bacon
1
Si alguien llama a Docker Build, ¿no se supone que quiere reconstruir sin el caché? ¿En qué caso de uso alguien querría construir una imagen y usar una imagen previamente construida? <rant> Acabo de perder un día porque una compilación anterior falló silenciosamente pero completó "exitoso" y estaba usando la imagen rota sin entender por qué las actualizaciones del script de compilación no funcionaban </rant>
Jeff
3
@Jeff Cuando desarrolle una imagen de acoplador, la creación de acoplador solo rehacerá las capas / pasos que se hayan modificado. Si tengo cinco pasos y agrego un nuevo paso en el índice 3, las capas asociadas con los pasos 1 y 2 se pueden reutilizar. Esto acelera enormemente el proceso de desarrollo
descama el
130

En algunos casos extremos, su única forma de evitar fallas de compilación recurrentes es ejecutando:

docker system prune

El comando le pedirá su confirmación:

WARNING! This will remove:
    - all stopped containers
    - all volumes not used by at least one container
    - all networks not used by at least one container
    - all images without at least one container associated to them
Are you sure you want to continue? [y/N]

Por supuesto, esta no es una respuesta directa a la pregunta, pero podría salvar algunas vidas ... Salvó la mía.

Wallace Sidhrée
fuente
8
agregar -a -f lo hace mejor
Ravi
1
@IulianOnofrei funciona para mí,Docker version 17.09.0-ce, build afdb6d4
Per Lundberg
1
@PerLundberg, actualicé dockera la misma versión y funciona, gracias.
Iulian Onofrei
1
Esto es una exageración para este escenario y no es una respuesta útil si no desea eliminar todo.
M_dk
1
Esto incluso eliminará las imágenes de contenedores detenidos, probablemente algo que no desea. Las versiones recientes de Docker tienen el comando docker builder prunepara borrar las capas de compilación en caché. Simplemente caí en la trampa después de copiar ciegamente los comandos del desbordamiento de la pila.
Evil Azrael
59

El comando docker build --no-cache .resolvió nuestro problema similar.

Nuestro Dockerfile fue:

RUN apt-get update
RUN apt-get -y install php5-fpm

Pero debería haber sido:

RUN apt-get update && apt-get -y install php5-fpm

Para evitar el almacenamiento en caché de la actualización e instalar por separado.

Ver: Mejores prácticas para escribir Dockerfiles

Youniteo
fuente
10
El "debería haber sido" es engañoso. Si Docker ve que tiene una copia en caché de RUN apt-get update && apt-get -y install php5-fpmusted, todavía verá que se reutiliza con el contenido anterior.
tripleee
10
En realidad, todavía tiene sentido unirlos, porque de lo contrario, si cambia la línea de instalación, seguirá usando la memoria caché del paquete anterior, que a menudo tendrá problemas si la memoria caché no está actualizada (por lo general, los archivos serán 404.)
John Chadwick
19

Para asegurarse de que su compilación se reconstruya por completo, incluida la comprobación de actualizaciones de la imagen base, use las siguientes opciones al compilar:

--no-cache - Esto forzará la reconstrucción de capas ya disponibles

--pull - Esto activará una extracción de la imagen base a la que se hace referencia desde FROM, lo que garantiza que tenga la última versión.

El comando completo se verá así:

docker build --pull --no-cache --tag myimage:version .

Las mismas opciones están disponibles para docker-compose:

docker-compose build --no-cache --pull
M_dk
fuente
13

No recomendaría usar --no-cacheen su caso.

Está ejecutando un par de instalaciones desde el paso 3 al 9 (por cierto, preferiría usar un revestimiento) y si no desea la sobrecarga de volver a ejecutar estos pasos cada vez que construye su imagen, puede modifique su Dockerfilecon un paso temporal antes de su wgetinstrucción.

Solía ​​hacer algo así RUN ls .y cambiarlo a RUN ls ./continuaciónRUN ls ./. y así sucesivamente para cada modificación realizada en el tarball recuperado porwget

Por supuesto, puede hacer algo como RUN echo 'test1' > test && rm testaumentar el número 'test1para cada iteración.

Parece sucio, pero que yo sepa, es la forma más eficiente de seguir beneficiándose del sistema de caché de Docker, que ahorra tiempo cuando tiene muchas capas ...

Olivier
fuente
3
La capacidad de no poder usar la memoria caché después de cierto punto es una característica solicitada por muchos (consulte github.com/moby/moby/issues/1996 para obtener alternativas para la eliminación de la memoria caché)
leszek.hanusz
13

Con docker-compose intente docker-compose up -d --build --force-recreate

Yash
fuente
6

La mayoría de la información aquí es correcta.
Aquí una recopilación de ellos y mi forma de usarlos.

La idea es apegarse al enfoque recomendado (compilación específica y sin impacto en otros objetos acoplados almacenados) e intentar el enfoque más radical (no compilar específico y con impacto en otros objetos acoplados almacenados) cuando no es suficiente.

Enfoque recomendado:

1) Forzar la ejecución de cada paso / instrucción en el Dockerfile:

docker build --no-cache 

o con docker-compose build:

docker-compose build --no-cache

También podríamos combinar eso con el upsubcomando que recrea todos los contenedores:

docker-compose build --no-cache &&
docker-compose up -d --force-recreate 

De esta manera, no use caché sino para el generador de acopladores y la imagen base referenciada con el FROM instrucción.

2) Limpie la memoria caché de Docker Builder (si usamos Buildkit, probablemente lo necesitemos):

docker builder prune -af

3) Si no queremos usar el caché de las imágenes principales, podemos intentar eliminarlas como:

docker image rm -f fooParentImage

En la mayoría de los casos, estas 3 cosas son perfectamente suficientes para permitir una construcción limpia de nuestra imagen.
Entonces deberíamos tratar de mantenernos en eso.

Enfoque más radical:

En los casos de esquina donde parece que algunos objetos en la memoria caché del acoplador todavía se usan durante la compilación y eso parece repetible, debemos tratar de comprender la causa para poder borrar la parte faltante de manera muy específica. Si realmente no encontramos una manera de reconstruir desde cero, hay otras formas, pero es importante recordar que generalmente eliminan mucho más de lo necesario. Por lo tanto, debemos usarlos con precaución en general cuando no estamos en un entorno local / de desarrollo.

1) Eliminar todas las imágenes sin al menos un contenedor asociado a ellas:

docker image prune -a

2) Eliminar muchas cosas más:

docker system prune -a

Que dice :

¡ADVERTENCIA! Esto eliminará:
  - todos los contenedores detenidos
  - todas las redes no utilizadas por al menos un contenedor
  - todas las imágenes sin al menos un contenedor asociado a ellas
  - todo el caché de compilación

El uso de ese comando súper eliminar puede no ser suficiente porque depende en gran medida del estado de los contenedores (en ejecución o no). Cuando ese comando no es suficiente, trato de pensar cuidadosamente qué contenedores acoplables pueden causar efectos secundarios en nuestra construcción de acopladores y permitir que estos contenedores salgan para permitir que se eliminen con el comando.

davidxxx
fuente
3

Puede administrar el caché del generador con docker builder

Para limpiar todo el caché sin aviso: docker builder prune -af

Shawn
fuente