Por que as imagens de contêiner do Docker são tão grandes?

177

Eu fiz uma imagem simples através do Dockerfile do Fedora (inicialmente 320 MB).

Adicionado o Nano (este pequeno editor de 1 MB), e o tamanho da imagem aumentou para 530 MB. Adicionei Git em cima disso (30 MB) e, em seguida, meu tamanho de imagem dispara para 830 MB.

Isso não é loucura?

Tentei exportar e importar contêiner para remover imagens históricas / intermediárias. Esse esforço economizou até 25 MB, agora o tamanho da minha imagem é 804 MB. Eu também tentei executar muitos comandos em um RUN, mas ainda estou recebendo os mesmos 830 MB iniciais.

Estou com minhas dúvidas se vale a pena usar o Docker. Quero dizer, eu mal instalei nada e estou atingindo 1 GB. Se eu tiver que adicionar coisas sérias, como um banco de dados e assim por diante, posso ficar sem espaço em disco.

Alguém sofre de tamanho ridículo de imagens? Como você lida com isso?

A menos que meu Dockerfile esteja terrivelmente incorreto?

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

mas é difícil imaginar o que poderia dar errado aqui.

zen
fonte
Onde e como você está medindo o tamanho do seu contêiner? Tem yum clean allalgum efeito no tamanho?
xeor
2
Espere que as imagens tenham um bom tamanho, pois são um acúmulo de imagens, imagens pai e imagem de base. Além disso, o yum instala, não apenas os aplicativos mencionados, mas também suas dependências. docs.docker.com/terms/container
rexposadas
2
Bem, minha "medição" é a execução da docker imagesqual, na última coluna, afirma um pesado 830MB. Talvez eu não saiba de fato qual é o tamanho real da minha imagem, já que o comando docker images indica que esse 830MB é de tamanho virtual. Mas, novamente, qual é o tamanho real da imagem?
Zen

Respostas:

118

Como o @rexposadas disse, as imagens incluem todas as camadas e cada camada inclui todas as dependências para o que você instalou. Também é importante observar que as imagens de base (como fedora:latesttendem a ser muito simples. Você pode se surpreender com o número de dependências que o software instalado possui.

Consegui diminuir significativamente sua instalação adicionando yum -y clean alla cada linha:

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

É importante fazer isso para cada RUN, antes que a camada seja confirmada ou as exclusões não removem os dados. Ou seja, em um sistema de arquivos de união / cópia na gravação, a limpeza no final não reduz realmente o uso do sistema de arquivos porque os dados reais já estão comprometidos com as camadas inferiores. Para contornar isso, você deve limpar em cada camada.

$ 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
fonte
1
Obrigado pelo seu esforço para investigar o caso, e sim, fui capaz de reduzir o tamanho da minha imagem para aproximadamente 635 MB (este é o valor apresentado como tamanho da imagem virtual após a execução de docker images). É possível remover / excluir / destruir essas camadas antigas? Para ser mais específico: eu gostaria de remover completamente (com base no seu exemplo) imagens: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a da história, para que o tamanho da minha imagem virtual seja mais ou menos o tamanho da imagem final, aqui ~ 260MB .
Zen
(Muito tempo para um comentário) A menos que o tamanho da imagem virtual não tenha nada a ver com o tamanho real da imagem no disco rígido? Se for esse o caso, como / onde verificar o tamanho real das minhas imagens?
Zen
Você poderia docker exporte depois docker importnovamente. Isso achataria as camadas. Eu não acho que isso reduziria o tamanho, mas eu poderia estar errado.
Andy
10
Sim, mas exportar não economiza muito. No entanto, consegui ler na web que o que posso observar no docker é o tamanho da imagem virtual. O tamanho real do disco rígido parece ser um mistério para mim, pois, no que diz respeito às informações oficiais, docker ps -smostra o tamanho real do disco rígido, que no meu caso era -1B. Isso parece razoável, menos 1 byte . Eu ganhei algum espaço no HDD ... parece legítimo.
Zen
@ Zen Desculpe, não estou seguindo. Então, o tamanho virtual e o tamanho do disco são duas coisas diferentes? O que exatamente o tamanho virtual mede?
24415 Jason
63

As imagens do Docker não são grandes, você está apenas criando imagens grandes.

A scratchimagem é 0B e você pode usá-lo para empacotar seu código, se for possível compilar seu código em um binário estático. Por exemplo, você pode compilar seu programa Go e empacotá-lo em cimascratch para criar uma imagem totalmente utilizável com menos de 5 MB.

A chave é não usar as imagens oficiais do Docker, pois elas são muito grandes. O zero não é tão prático assim, então eu recomendo usar o Alpine Linux como sua imagem base. Tem ~ 5 MB e adicione apenas o necessário para o seu aplicativo. Este post sobre microcontainers mostra como criar imagens muito pequenas baseadas no Alpine.

ATUALIZAÇÃO: as imagens oficiais do Docker agora são baseadas em alpinos, portanto, é bom usá-las agora.

Travis Reeder
fonte
2
Ótima solução !, É tão importante parar o desperdício e ficar mais seguro ---> menos código -> menos preocupação.
Ran Davidovitz
1
Felizmente, as imagens oficiais do Docker também estão se movendo para usar uma base alpina, para que mais e mais você possa usar as imagens regulares em vez de depender das versões do iron.io. Veja brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels
@ Travis R, seu link para postar sobre microcontainers parece ter se mudado para outro lugar. Esta é a postagem que você deseja vincular?
Alexander F.
@AlexanderF. Links fixos, obrigado por me informar.
Travis Reeder
28

Aqui estão mais algumas coisas que você pode fazer :

  • Evite vários RUNcomandos onde puder. Coloque o máximo possível em um RUNcomando (usando &&)
  • limpe ferramentas desnecessárias como wget ou git (que você só precisa baixar ou criar, mas não para executar seu processo)

Com esses dois AND as recomendações de @Andy e @michau, eu fui capaz de redimensionar minha imagem nodejs de 1.062 GB para 542 MB.

Edit: Mais uma coisa importante: "Demorei um pouco para entender realmente que cada comando do Dockerfile cria um novo contêiner com os deltas. [...] Não importa se você rm -rf os arquivos em um comando posterior; eles continuam a existir em algum contêiner de camada intermediária ". Então agora eu consegui colocar apt-get install, wget, npm install(com dependências git) e apt-get removeem um único RUNcomando, então agora a minha imagem tem apenas 438 MB.

Editar 29/06/17

Com o Docker v17.06, surgem novos recursos para os Dockerfiles: você pode ter várias FROMinstruções em um Dockerfile e apenas as últimas coisas FROMestarão na sua imagem final do Docker. Isso é útil para reduzir o tamanho da imagem, por exemplo:

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

Irá resultar em uma imagem com apenas a imagem base nodejs mais o conteúdo de / var / my-project desde os primeiros passos - mas sem o ruby, python, git, openssh e gcc!

Munchkin
fonte
22

Sim, esses tamanhos são ridículos, e eu realmente não tenho idéia do por que tão poucas pessoas percebem isso.

Eu criei uma imagem do Ubuntu que é realmente mínima (ao contrário de outras chamadas imagens "mínimas"). É chamado textlab/ubuntu-essentiale tem 60 MB.

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

A imagem acima tem 82 MB após a instalação do nano.

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

O Git tem muitos outros pré-requisitos, portanto a imagem fica maior, cerca de 192 MB. Ainda é menor que o tamanho inicial da maioria das imagens.

Você também pode dar uma olhada no script que escrevi para criar a imagem mínima do Ubuntu para o Docker . Talvez você possa adaptá-lo ao Fedora, mas não sei quanto você poderá desinstalar.

michau
fonte
13

O seguinte me ajudou muito:

Após remover os pacotes não utilizados (por exemplo, redis 1200 mb liberados) dentro do meu contêiner, fiz o seguinte:

  1. docker export [containerID] -o containerername.tar
  2. docker import -m "confirmar mensagem aqui" containsername.tar imagename: tag

As camadas ficam achatadas. O tamanho da nova imagem será menor porque removi os pacotes do contêiner, conforme indicado acima.

Demorou muito tempo para entender isso e é por isso que adicionei meu comentário.

Jeffrey Schmitz
fonte
Você pode combinar as duas etapas em uma única etapadocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar
8

Para práticas recomendadas, você deve executar um único comando RUN, porque cada instrução RUN no Dockerfile grava uma nova camada na imagem e cada camada requer espaço extra no disco. Para manter o número mínimo de camadas, qualquer manipulação de arquivo, como instalar, mover, extrair, remover, etc, deve ser idealmente feita sob uma única instrução RUN

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

O Docker Squash é uma solução muito boa para isso. você pode, $packagemanager cleanna última etapa, em vez de em todas as linhas e, em seguida, basta executar uma aba Docker para se livrar de todas as camadas.

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

jeremyjjbrown
fonte
0

Sim, o sistema de camadas é bastante surpreendente. Se você possui uma imagem base e a incrementa, faça o seguinte:

# 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/* 

A imagem tem exatamente o mesmo tamanho. Essencialmente, isso significa que você precisa colocar em suas etapas RUN muitas técnicas de extração, instalação e limpeza para tornar as imagens tão pequenas quanto o software instalado.

Isso torna a vida muito mais difícil ...

O dockerBuild está ausente nas etapas RUN sem confirmação.

99Sono
fonte