COPIAR com janela de encaixe, mas com exclusão

231

Em um arquivo Docker, eu tenho

COPY . .

Eu quero excluir um diretório inteiro, no meu caso, o diretório node_modules.

Algo assim:

   COPY [all but **/node_modules/**] .

Isso é possível com o Docker?

Alexander Mills
fonte
23
Que tal .dockerignore?
Anthony Sottile
Estou à procura de resposta a esta questão relacionada: stackoverflow.com/questions/50547489/...
Alexander Mills

Respostas:

377

Crie um arquivo .dockerignoreno diretório de contexto de construção da janela de encaixe (portanto, nesse caso, provavelmente um diretório pai de node_modules) com uma linha:

**/node_modules

embora você provavelmente só queira:

node_modules

Informações sobre dockerignore: https://docs.docker.com/engine/reference/builder/#dockerignore-file

vith
fonte
5
obrigado, então a "COPY." comando não precisa mudar, eu acho
Alexander Mills
Na verdade /config/nginx/ /config/logstash/, não ls config/ gunicorn logs logstash nginx
:,
3
@SalahAdDin pelo mesmo motivo que não escreveu ls /config/, tentou adicionar esses caminhos ao seu .dockerignore sem o líder /?
24418 Pablo Pablo
8
Apenas node_modulesnão funciona em subdiretórios.
Rustyx
5
Isto realmente não resolver o problema, se você quiser tê-lo COPY'd mas não apenas nessa camada ...
Wes
33

Para aqueles que não podem usar um arquivo .dockerignore (por exemplo, se você precisar do arquivo em uma CÓPIA, mas não em outra):

Sim, mas você precisa de várias instruções de CÓPIA. Especificamente, você precisa de uma CÓPIA para cada letra do nome do arquivo que deseja excluir.

COPY [^n]*    # All files that don't start with 'n'
COPY n[^o]*   # All files that start with 'n', but not 'no'
COPY no[^d]*  # All files that start with 'no', but not 'nod'

Continue até ter o nome completo do arquivo ou apenas o prefixo que você tem certeza de que não terá outros arquivos.

Alex
fonte
1
Isso não vai acabar, porque você receberá um COPY failed: no source files were specifiedquando não houver arquivos começando com 'não', mas não 'aceno'.
Mheck #
1
Como alternativa, você pode usar dois subdiretórios diferentes (para destinos de cópia diferentes), para que, por exemplo, na minha configuração do nginx, eu src//var/wwwe /conf/nginx.confvá para /etc/nginx/conf.d/default.conf. Além disso, você pode copiar tudo e RUN rm -r confmais tarde (também mantenha a árvore de origem). Gostaria de saber se alguém tem outra sugestão.
Yuval
1
Qual seria uma solução para tipos de arquivos específicos ou finais de arquivos, se eu o fizesse assim?
Lea Reimann
A única desvantagem dessa abordagem é que a estrutura da pasta é achatada
Islam Q.
Se você tiver apenas alguns diretórios a serem copiados (diga apenas '/ app' ou '/ src'). Uma maneira mais simples seria copiar diretórios individualmente (para manter sua estrutura) e, em seguida, você precisará apenas de um COPY [^node_modules]*para copiar todos os arquivos de nível superior.
smdufb 25/06
9

No meu caso, meu Dockerfile continha uma etapa de instalação, que produzia o vendordiretório (o equivalente em PHP node_modules). Então, COPYeste diretório passa para a imagem final do aplicativo. Portanto, eu não poderia colocar vendorno meu .dockerignore. Minha solução foi simplesmente excluir o diretório antes de executar composer install(o equivalente em PHP a npm install).

FROM composer AS composer
WORKDIR /app
COPY . .
RUN rm -rf vendor \
    && composer install 

FROM richarvey/nginx-php-fpm
WORKDIR /var/www/html
COPY --from=composer /app .

Essa solução funciona e não incha a imagem final, mas não é ideal, porque o vendordiretório no host é copiado no contexto do Docker durante o processo de construção, o que aumenta o tempo.

Cameron Hudson
fonte
3
Observe com certeza por que você deve remover composer.lockantes composer install. Sem o arquivo de bloqueio, um conjunto diferente de dependências (a pasta do fornecedor) pode ser instalado quando você criar na próxima vez.
Lacek
1
@Lacek: Você está certo. Aprendi melhor desde que publiquei isso.
Cameron Hudson
1
O @CameronHudson talvez atualize sua resposta original antes que as pessoas copiem / colem essa má prática.
Robin van Baalen
2

Adicionar .dockerignore funciona para mim. Um ponto adicional Para aqueles que estão tentando esta solução no Windows , o Windows não permitirá que você crie um arquivo .dockerignore (pois, por padrão, não permite a criação de arquivos começando com.)

Para criar esse arquivo começando com. no Windows , inclua também um ponto final, como: .dockerignore.e pressione enter (desde que você tenha ativado as opções de extensão de exibição nas opções de pasta)

Paras Patidar
fonte
6
Você pode criar um arquivo no Windows que comece com um ponto e também com um ponto.
Jim Pedid
0

Excluindo node_modules do diretório atual

node_modules

Excluindo node_modules em quaisquer subdiretórios imediatos

*/node_modules

Aqui estão os documentos oficiais

kta
fonte