construir contexto para imagem docker muito grande

142

Criei alguns diretórios diferentes na minha máquina host enquanto tento aprender sobre o Docker apenas para manter meus arquivos docker organizados. Meu Dockerfile que acabei de executar fica assim:

FROM crystal/centos
MAINTAINER crystal

ADD ./rpms/test.rpm ./rpms/ 
RUN yum -y --nogpgcheck localinstall /rpms/test.rpm 

Minha rpm real é de apenas 1 GB. Mas quando tento fazer sudo docker build -t="crystal/test" ., recebo o contexto de construção para o daemon Docker de 3,5 GB. Existe alguma outra coisa que eu desconheço enquanto você continua criando imagens do Docker? Minha memória está se acumulando à medida que construo mais imagens em meus outros diretórios na minha máquina host?

Cristal
fonte
2
O contexto de construção são todos os arquivos / diretórios no diretório atual.
Nabin
Mantenha apenas os arquivos necessários para a construção neste diretório. Ou seja, o Dockerfile e quaisquer arquivos / diretórios locais copiados / adicionados à imagem de compilação no Dockerfile. Além disso, faça uso de.dockerignore
Vishrant

Respostas:

266

O cliente do Docker envia todo o "contexto de construção" para o daemon do Docker. Esse contexto de construção (por padrão) é o diretório inteiro Dockerfileem que está (portanto, a rpmsárvore inteira ).

Você pode configurar um .dockerignorearquivo para que o Docker ignore alguns arquivos. Você pode experimentar isso.

Como alternativa, você pode mover sua rpmspasta um nível de diretório acima do seu Dockerfile, e apenas ligar novamente test.rpmpara o Dockerfilediretório da pasta .


Como muitos usuários apontaram nos comentários, é necessário adicionar a .gitpasta à.dockerignore qual foi a causa de uma diferença de 150 MB -> 5 GB no meu caso.

Thomas Orozco
fonte
4
Infelizmente, parece que a ligação simbólica não é possível nesse caso, pois o ADDcomando não segue os links sym durante uma compilação. Veja: github.com/docker/docker/issues/1676
JimmidyJoo
5
salva-vidas! Rails desenvolvedores: se esqueça de adicionar tmp loga .dockerignore+ outros entes personalizados
equivalent8
7
não se esqueça de adicionar pasta .git para .dockerignore arquivo (supondo que você está usando git)
DsnCode
8
Sim, a .gitpasta está incluída por padrão - isso definitivamente me chamou a atenção.
Paul Suart
1
Qual é o "contexto de construção" exatamente? Tentei procurar esses arquivos usando o comando docker build RUN, mas não vejo os arquivos na minha pasta Dockerfile dentro do sistema de arquivos docker (durante o tempo de construção.) Alguém pode me dar um exemplo simples de como o contexto de construção é útil?
Patrick
52

Atualização 2019

A partir do Docker v18.06, há uma opção para usar um novo construtor de imagens chamado Build Kit .

Ele vem com o Docker, não é necessário instalar nada. É compatível com a Dockerfilesintaxe, não há necessidade de alterar o Dockerfile.

Legado Docker Build vs Novo Docker BuildKit

Aqui está um exemplo de criação de uma imagem com um enorme arquivo não utilizado no diretório de construção:

Construção herdada do Docker:

$ time docker image build --no-cache .
Sending build context to Docker daemon  4.315GB
[...]
Successfully built c9ec5d33e12e

real    0m51.035s
user    0m7.189s
sys 0m10.712s

Novo BuildKit do Docker:

$ time DOCKER_BUILDKIT=1 docker image build --no-cache .
[+] Building 0.1s (5/5) FINISHED                                                
 => [internal] load build definition from Dockerfile                       0.0s
 => => transferring dockerfile: 37B                                        0.0s
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
[...]
 => => writing image sha256:ba5bca3a525ac97573b2e1d3cb936ad50cf8129eedfa9  0.0s

real    0m0.166s
user    0m0.034s
sys 0m0.026s

A única mudança é a DOCKER_BUILDKIT=1variável de ambiente, a diferença no tempo é enorme.

.dockerignore Arquivo

Observe que o .dockerignorearquivo ainda é válido e útil. Alguns Dockerfilecomandos como COPY . .ainda levarão em conta as .dockerignoreregras. Mas os arquivos laterais no diretório de construção (não mencionados no Dockerfile) não estão mais sendo copiados como um "contexto de construção" pelo BuildKit.

Andriy Berestovskyy
fonte
1
É importante observar que atualmente não há suporte para DOCKER_BUILDKIT para contêineres do Windows. (Somente Linux, listado sob limitações: docs.docker.com/develop/develop-images/build_enhancements )
Vaccano
18

Corrigi-o movendo meu Dockerfile e docker-compose.yml para uma subpasta e funcionou muito bem. Aparentemente, o docker envia a pasta atual para o daemon e minha pasta foi de 9 GB.

Emad
fonte
4
Este método fornece o caminho proibido: fora do erro do contexto de construção, se um arquivo de um diretório pai estiver sendo copiado, alguma solução para isso?
Kitwradr
8

Se você tiver um .dockerignorearquivo e o contexto de construção ainda for grande, poderá verificar o que está sendo enviado para o contexto de construção do Docker usando o Silver Searcher :

ag --path-to-ignore .dockerignore --files-with-matches

Observe que alguns **padrões podem não funcionar corretamente.

Veja esta edição do Github para comentários adicionais: https://github.com/moby/moby/issues/16056

Luís Bianchin
fonte
4

No meu caso, foi quando eu executo com -fargumentos errados - sem o caminho para o diretório em que estava localizado o Dockerfile

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile /home/DF/ - certo

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile - errado

FreeStyler
fonte
1

Se você deseja ter controle total do seu contexto de construção, também poderá construir o contêiner completamente, sem nenhum contexto e COPYdados relevantes no contêiner posteriormente.

docker build - < Dockerfile

Uma desvantagem disso seria que, com essa abordagem, você pode apenas ADDno arquivo docker referenciar uma URL remota, e não os arquivos do host local.

Consulte https://docs.docker.com/engine/reference/commandline/build/#build-with--

Christian.D
fonte
0

Eu tive o mesmo problema que o FreeStyler. No entanto, eu estava construindo a partir de um diretório acima do meu contexto. Portanto, os argumentos -f estavam corretos, o contexto estava incorreto.

project 
|
-------docker-dir 

Construindo a partir do docker-dir, o seguinte foi bom

docker build -t br_base:0.1 . 

Construindo a partir do diretório-dock, o contexto de construção foi alterado. Portanto, eu precisava alterar o contexto no comando. O contexto é dado pelo '.' no comando acima.

O novo comando do diretório do projeto deve ser

docker build -t br_base:0.1 ./base

O contexto aqui é fornecido pela './base'

BravoRomeo23
fonte
0

se você estiver criando imagem e recebendo o contexto de construção do envio de mensagens para o daemon do docker, o que está demorando para ser copiado,

adicione o arquivo .dockerignore . deve incluir os arquivos ou diretório que não precisam ser copiados.

Pandit Shashikant
fonte
0

Para NodeJS Application, adicione um .dockerignorearquivo ao diretório raiz do projeto e, dentro do .dockerignorearquivo, adicione o seguinte

node_modules
dist
Bernard Nongpoh
fonte