¿Por qué las imágenes del contenedor Docker son tan grandes?

177

Hice una imagen simple a través de Dockerfile desde Fedora (inicialmente 320 MB).

Se agregó Nano (este pequeño editor de 1 MB de tamaño), y el tamaño de la imagen ha aumentado a 530 MB. Agregué Git además de eso (30-ish MB), y luego mi tamaño de imagen se disparó a 830 MB.

¿No es una locura?

Intenté exportar e importar contenedores para eliminar el historial / imágenes intermedias. Este esfuerzo ahorró hasta 25 MB, ahora mi tamaño de imagen es de 804 MB. También he intentado ejecutar muchos comandos en uno RUN, pero aún obtengo los mismos 830 MB iniciales.

Tengo mis dudas sobre si vale la pena usar Docker. Quiero decir, apenas instalé nada y estoy llegando a 1GB. Si tuviera que agregar algunas cosas serias como una base de datos, etc., podría quedarme sin espacio en disco.

¿Alguien sufre de un tamaño ridículo de imágenes? ¿Cómo lo afrontas?

¿A menos que mi Dockerfile sea horriblemente incorrecto?

FROM fedora:latest
MAINTAINER Me NotYou <[email protected]>
RUN yum -y install nano
RUN yum -y install git

Pero es difícil imaginar qué podría salir mal aquí.

zen
fuente
¿Dónde y cómo mide el tamaño de su contenedor? ¿ yum clean allTiene algún efecto en el tamaño?
xeor
2
Espere que las imágenes tengan un buen tamaño, ya que es una acumulación de su imagen, imágenes primarias y la imagen base. Además, yum instala, no solo las aplicaciones mencionadas, sino también sus dependencias. docs.docker.com/terms/container
rexposadas
2
Bueno, mi "medición" es la ejecución de la docker imagescual en la última columna indica un considerable 830MB. Es posible que no sepa cuál es el tamaño real de mi imagen, ya que el comando docker images indica que este 830 MB es de tamaño virtual. Pero, de nuevo, ¿cuál es el tamaño real de la imagen?
Zen

Respuestas:

118

Como dijo @rexposadas, las imágenes incluyen todas las capas y cada capa incluye todas las dependencias de lo que instaló. También es importante tener en cuenta que las imágenes base (como fedora:latesttienden a ser muy básicas) . Puede sorprenderse por la cantidad de dependencias que tiene su software instalado.

Pude hacer que su instalación sea significativamente más pequeña al agregar yum -y clean alla cada línea:

FROM fedora:latest
RUN yum -y install nano && yum -y clean all
RUN yum -y install git && yum -y clean all

Es importante hacer eso para cada RUN, antes de que se confirme la capa, o de lo contrario las eliminaciones no eliminan los datos. Es decir, en un sistema de archivos de unión / copia en escritura, la limpieza al final no reduce realmente el uso del sistema de archivos porque los datos reales ya están comprometidos con las capas inferiores. Para evitar esto, debes limpiar cada capa.

$ docker history bf5260c6651d
IMAGE               CREATED             CREATED BY                                      SIZE
bf5260c6651d        4 days ago          /bin/sh -c yum -y install git; yum -y clean a   260.7 MB
172743bd5d60        4 days ago          /bin/sh -c yum -y install nano; yum -y clean    12.39 MB
3f2fed40e4b0        2 weeks ago         /bin/sh -c #(nop) ADD file:cee1a4fcfcd00d18da   372.7 MB
fd241224e9cf        2 weeks ago         /bin/sh -c #(nop) MAINTAINER Lokesh Mandvekar   0 B
511136ea3c5a        12 months ago                                                       0 B
Andy
fuente
1
Gracias por su esfuerzo para investigar el caso, y sí, pude reducir el tamaño de mi imagen a aproximadamente 635 MB (este es el valor presentado como tamaño de imagen virtual después de la ejecución de docker images). ¿Es posible eliminar / eliminar / destruir esas viejas capas? Para ser más específico: me gustaría eliminar por completo (basándome en su ejemplo) imágenes: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a del historial, para que el tamaño de mi imagen virtual sea más o menos igual que el tamaño de la imagen final, aquí ~ 260MB .
Zen
(Demasiado tiempo para 1 comentario) ¿A menos que el tamaño de la imagen virtual no tenga nada que ver con el tamaño real de la imagen en el HDD? Si este es el caso, ¿cómo / dónde verificar el tamaño real de mis imágenes?
Zen
Podrías docker exporty luego docker importotra vez. Eso aplanaría las capas. No creo que reduzca el tamaño, pero podría estar equivocado.
Andy
10
Sí, pero exportar no ahorra mucho. No obstante, pude leer en la web que lo que puedo observar en Docker es el tamaño de la imagen virtual. El tamaño real en HDD parece ser un misterio para mí ya que con respecto a la información oficial docker ps -smuestra el tamaño real en HDD, que en mi caso fue -1B. Eso suena razonable, menos 1 byte . He ganado algo de espacio en HDD ... parece legítimo.
Zen
@Zen Lo siento, no te estoy siguiendo. ¿Entonces el tamaño virtual y el tamaño del disco son 2 cosas diferentes? ¿Qué mide exactamente el tamaño virtual?
Jason
63

Las imágenes de Docker no son grandes, solo está creando imágenes grandes.

La scratchimagen es 0B y puede usarla para empaquetar su código si puede compilar su código en un binario estático. Por ejemplo, puede compilar su programa Go y empaquetarlo encimascratch para crear una imagen totalmente utilizable que sea inferior a 5 MB.

La clave es no usar las imágenes oficiales de Docker, son demasiado grandes. Scratch tampoco es tan práctico, así que recomiendo usar Alpine Linux como imagen base. Es ~ 5 MB, luego solo agregue lo que se requiere para su aplicación. Esta publicación sobre Microcontenedores le muestra cómo construir imágenes muy pequeñas basadas en Alpine.

ACTUALIZACIÓN: las imágenes oficiales de Docker se basan en alpino ahora, por lo que son buenas para usar ahora.

Travis Reeder
fuente
2
¡Gran solución! Es muy importante detener el desperdicio y mantenerse más seguro ---> menos código -> menos preocupación.
Ran Davidovitz
1
Afortunadamente, las imágenes oficiales de Docker también se están moviendo para usar una base Alpine, por lo que cada vez más puedes usar las imágenes normales en lugar de depender de las versiones de iron.io. Ver brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels el
@Travis R, su enlace para publicar sobre microcontenedores parece haberse movido a otro lugar. ¿Es esta la publicación que querías vincular?
Alexander F.
@AlexanderF. Enlaces fijos, gracias por hacérmelo saber.
Travis Reeder
28

Aquí hay algunas cosas más que puede hacer :

  • Evita múltiples RUNcomandos donde puedas. Ponga tanto como sea posible en un RUNcomando (usando &&)
  • limpia herramientas innecesarias como wget o git (que solo necesitas para descargar o crear cosas, pero no para ejecutar tu proceso)

Con estos Y las recomendaciones de @Andy y @michau pude cambiar el tamaño de mi imagen de nodejs de 1.062 GB a 542 MB.

Editar: Una cosa más importante: "Me tomó un tiempo comprender realmente que cada comando Dockerfile crea un nuevo contenedor con los deltas. [...] No importa si rm -rf los archivos en un comando posterior; continúan existiendo en algún contenedor de capa intermedia ". Así que ahora logrado poner apt-get install, wget, npm install(con dependencias GIT) y apt-get removeen un solo RUNcomando, por lo que ahora mi imagen sólo tiene 438 MB.

Editar 29/06/17

Con Docker v17.06, hay nuevas características para Dockerfiles: puede tener varias FROMdeclaraciones dentro de un Dockerfile y solo las últimas cosas FROMestarán en su imagen final de Docker. Esto es útil para reducir el tamaño de la imagen, por ejemplo:

FROM nodejs as builder
WORKDIR /var/my-project
RUN apt-get install ruby python git openssh gcc && \
    git clone my-project . && \
    npm install

FROM nodejs
COPY --from=builder /var/my-project /var/my-project

Dará como resultado una imagen que solo tenga la imagen base de nodejs más el contenido de / var / my-project de los primeros pasos, ¡pero sin ruby, python, git, openssh y gcc!

Munchkin
fuente
22

Sí, esos tamaños son ridículos, y realmente no tengo idea de por qué tan poca gente lo nota.

Hice una imagen de Ubuntu que en realidad es mínima (a diferencia de otras llamadas imágenes "mínimas"). Se llama textlab/ubuntu-essentialy tiene 60 MB.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano

La imagen de arriba es de 82 MB después de instalar nano.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git

Git tiene muchos más requisitos previos, por lo que la imagen se agranda, aproximadamente 192 MB. Eso es aún menos que el tamaño inicial de la mayoría de las imágenes.

También puedes echar un vistazo a la secuencia de comandos que escribí para crear la imagen mínima de Ubuntu para Docker . Quizás pueda adaptarlo a Fedora, pero no estoy seguro de cuánto podrá desinstalar.

michau
fuente
13

Lo siguiente me ayudó mucho:

Después de eliminar los paquetes no utilizados (por ejemplo, redis 1200 mb liberados) dentro de mi contenedor, hice lo siguiente:

  1. docker export [containerID] -o containername.tar
  2. docker import -m "enviar mensaje aquí" containername.tar imagename: etiqueta

Las capas se aplanan. El tamaño de la nueva imagen será menor porque he eliminado los paquetes del contenedor como se indicó anteriormente.

Me tomó mucho tiempo entender esto y es por eso que agregué mi comentario.

Jeffrey Schmitz
fuente
Puede combinar ambos pasos en un solo pasodocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar
8

Para la mejor práctica, debe ejecutar un solo comando RUN, porque cada instrucción RUN en el Dockerfile escribe una nueva capa en la imagen y cada capa requiere espacio adicional en el disco. Para mantener las capas de números al mínimo, cualquier manipulación de archivos como instalar, mover, extraer, eliminar, etc., idealmente debe realizarse bajo una sola instrucción RUN

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all
tmz83
fuente
4

Docker Squash es una buena solución para esto. puedes $packagemanager cleanhacerlo en el último paso en lugar de en cada línea y luego simplemente ejecutar una docker squash para deshacerte de todas las capas.

https://github.com/jwilder/docker-squash

jeremyjjbrown
fuente
0

Sí, el sistema de capas es bastante sorprendente. Si tiene una imagen base y la incrementa haciendo lo siguiente:

# Test
#
# VERSION       1

# use the centos base image provided by dotCloud
FROM centos7/wildfly
MAINTAINER JohnDo 

# Build it with: docker build -t "centos7/test" test/

# Change user into root
USER root

# Extract weblogic
RUN rm -rf /tmp/* \
    && rm -rf /wildfly/* 

La imagen tiene exactamente el mismo tamaño. Eso significa esencialmente que debes lograr poner en tus pasos de RUN mucha magia de extracción, instalación y limpieza para hacer que las imágenes sean tan pequeñas como el software instalado.

Esto hace la vida mucho más difícil ...

A dockerBuild le faltan pasos de ejecución sin confirmación.

99Sono
fuente