
Por muito tempo, desenvolvi um aplicativo usando Docker com um contêiner intermediário, por exemplo, eu construiria myapp:base
um que tivesse todos os arquivos principais copiados:
FROM ubuntu:17.10
ADD app /app
Agora, o contêiner principal myapp:release
pode ser criado simplesmente com este
FROM myapp:base
ADD app /app
Alguns arquivos podem ser modificados no app
diretório e eu acabaria com uma pequena camada extra.
Recentemente, porém, esta final ADD
resultou em uma camada muito maior e suspeito que esteja relacionada a uma atualização do Docker (estou usando o Docker versão 18.02.0-ce, build fc4de44)
Alguma coisa mudou na forma como o Docker descobre o que é diferente? Como posso voltar a uma compilação eficiente que possui apenas um pequeno número de arquivos atualizados em uma camada?
Passos para reproduzir:
# make a dummy dir with a 64kb file in it
mkdir -p files
truncate -s 64k files/64k.file
# base container has a copy of the files
cat << EOF > Dockerfile.base
FROM ubuntu:16.04
COPY files/ /root/
EOF
# derived container should just have any updates
cat << EOF > Dockerfile.derived
FROM q899941:base
COPY files/ /root/
EOF
# build them....
docker build --file Dockerfile.base -t q899941:base .
docker build --file Dockerfile.derived -t q899941:derived .
# now let's review the layers
docker history q899941:derived
eu obtenho esse resultado
IMAGE CREATED CREATED BY SIZE
4e1eb5168d55 Less than a second ago /bin/sh -c #(nop) COPY dir:8e20ede288278c71e… 65.5kB
022626ac5cf0 Less than a second ago /bin/sh -c #(nop) COPY dir:8e20ede288278c71e… 65.5kB
0458a4468cbc 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 5 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 2.76kB
<missing> 5 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B
<missing> 5 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:a3344b835ea6fdc56… 112MB
A camada superior tem 64 KB, embora nenhum arquivo tenha sido alterado.
Responder1
Parece que este é umproblema conhecido, mas não um com o qual um número suficiente de pessoas se importe!
- Existe uma maneira de adicionar apenas arquivos alterados a uma imagem do docker como uma nova camada - sem recorrer ao commit do docker?é uma questão StackOverflow que cobre o mesmo terreno.
- Parece que o comportamento que eu esperava funcionou com o driver de armazenamento de sobreposição, mas depois de algumas atualizações do sistema comecei a usar o overlay2, que copiará todos os arquivos em uma camada e não apenas os alterados
- Embora uma solução seja reverter para sobreposição, ela parece bastante obsoleta neste momento.Um método alternativo para construir camadas 'diff' é detalhado aqui
Acabei fazendo uma coisa simples mencionada em um doscomentáriosno relatório de bug:
#clean up any previous attempt...
docker rm -f uniquename 2> /dev/null
# now take your base container, mount the updated dir as /src
# then rsync from /src to the target dir - only updated files will
# actually be written, and we use --delete to ensure removed files are
# taken out...
docker run --name uniquename \
-v ~/repo/mycode:/src \
${REPO}/${IMAGE}:${BASE} \
rsync -ar --no-owner --no-group \
--exclude-from '/src/.dockerignore' --delete \
/src/ /app/
# we can commit that updated container with a tag
docker commit uniquename ${REPO}/${IMAGE}:${NEW_TAG}
Mais uma coisa: esta solução pareceu eliminar o CMD
comando de inicialização padrão existente que fornecia aos meus contêineres. Então, depois de adicionar essa camada diff, tive outro Dockerfile para criar um contêiner a partir da compilação 'diff' acima com o CMD
adicionado novamente.