As instruções COPY
e ADD
são utilizadas em arquivos Dockerfile
e possuem propósitos semelhantes.
Embora existam pequenas diferenças no escopo de sua aplicação, elas executam essencialmente a mesma operação: Copiar arquivos/diretórios de uma origem para um destino dentro da imagem.
Ok, então qual é a diferença entre Docker ADD
e COPY
? 🤔
Continue lendo…
Docker ADD
A instrução ADD
está presente no Docker desde as suas primeiras versões.
O comando copia arquivos/diretórios para o destino especificado dentro do container, a sintaxe básica do ADD
possui duas formas:
ADD [--chown=<user>:<group>] <src>... <dest> #1
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] #2
Esse comando espera como argumentos a origem (<src>
) e o destino (<dest>
).
Se a origem for um diretório, o ADD
irá copiar tudo dentro dele, incluindo os metadados do sistema de arquivos do SO1.
Outro ponto de atenção está no caminho, se contiver espaços em branco deverá ser utilizada a segunda forma da instrução.
Nota: O argumento
--chown
é compatível apenas com imagens usadas para criar contêineres Linux.
Por exemplo, se o arquivo estiver disponível localmente você poderá fazer algo como:
ADD coderarena.txt docs/
Para os casos em que você deseja copiar um diretório e todos os arquivos contidos nele, a instrução será:
ADD coderarena/sources/ /sources/
Note que existe uma diferença quando informamos o destino com uma /
no início, podendo ser um caminho relativo ou absoluto em relação ao WORKDIR
:
<dest>/
: especifica um caminho de destino relativo<WORKDIR>/relativeDir/
./<dest>/
: especifica um caminho de destino absoluto/relativeDir/
.
Além dos arquivos locais, o comando ADD
também permite a cópia de arquivos externos por meio de uma URL informada no parâmetro de origem.
ADD https://coderarena.com.br/sources/test.txt /sources
Um recurso adicional é a possibilidade de copiar arquivos compactados e extraí-los automaticamente no destino.
Essa operação não se aplica a arquivos externos, ou seja, apenas arquivos salvos localmente podem ser descompactados pelo comando ADD
.
Esse é um caso de uso válido, sendo utilizado pela imagem Alpine.
ADD coderarena.tar.gz docs/
Docker COPY
O comando ADD
possui diversas funcionalidades que variam de acordo com o tipo da origem. Essa variedade trouxe uma série de problemas para o Docker, se comportando de forma extremamente imprevisível.
Sendo capaz de realizar extrações ao mesmo tempo em que copia arquivos compactados, tornou-se bastante comum casos em que apenas copiava quando você esperava por uma extração e extração quando queria apenas copiar.
Por essa razão, o Docker teve que introduzir um comando adicional para realizar a duplicação de conteúdo, haja visto que, não poderia simplesmente remover o comando problemático por questões de compatibilidade.
O COPY
tem uma responsabilidade bastante simples: copiar os itens da origem, sem nenhuma manipulação automática, para o destino.
A instrução não é capaz de fazer a extração de arquivos compactados e, lida apenas com cópias de arquivos/diretórios presentes no host de build da imagem.
Docker COPY vs ADD
Com base em tudo o que aprendemos até aqui, está claro que você deve usar o COPY
por padrão, além disso, o Docker possui um guia de boas práticas na escrita de Dockerfiles
que desencoraja o uso do comando ADD
.
Existe apenas uma situação na qual ele será indicado, ao extrair arquivos .tar
locais para a sua imagem.
Para download e descompactação de arquivos externos, você pode substituir o ADD
por curl ou wget no comando RUN
do seu Dockerfile
, abaixo um exemplo:
Ruim
ADD https://coderarena.com.br/sources/plugins.tar.xz /tmp/
RUN tar -xJf /tmp/plugins.tar.xz -C /tmp
RUN make -C /tmp all
Recomendado
RUN mkdir -p /tmp \
&& curl -SL https://coderarena.com.br/sources/plugins.tar.xz | tar -xJC /tmp \
&& make -C /tmp all
Sempre use COPY
, é mais simples e explícito, exceto quando houver a necessidade de extração de um arquivo .tar
local.
Referências:
- https://docs.docker.com/engine/reference/builder/#add
- https://docs.docker.com/engine/reference/builder/#copy
- https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy
- O termo “SO” é uma abreviação para Sistema Operacional.↩