Como posso incluir arquivos fora do contexto de construção do Docker usando o comando "ADD" no arquivo do Docker?
Na documentação do Docker:
O caminho deve estar dentro do contexto da construção; não é possível ADICIONAR ../something/something, porque a primeira etapa de uma construção do docker é enviar o diretório de contexto (e subdiretórios) para o daemon do docker.
Não quero reestruturar todo o meu projeto apenas para acomodar o Docker nesta questão. Quero manter todos os meus arquivos do Docker no mesmo subdiretório.
Além disso, parece que o Docker ainda não suporta (e talvez nunca) os links simbólicos: O comando Dockerfile ADD não segue os links simbólicos no host # 1676.
A única outra coisa em que consigo pensar é incluir uma etapa de pré-compilação para copiar os arquivos no contexto de compilação do Docker (e configurar meu controle de versão para ignorar esses arquivos). Existe uma solução melhor para isso?
FROM
continuar a partir daí. Eu não alteraria a estrutura do projeto para acomodar o Docker (ou qualquer ferramenta de construção).Respostas:
A melhor maneira de contornar isso é especificar o Dockerfile independentemente do contexto de construção, usando -f.
Por exemplo, este comando dará ao comando ADD acesso a qualquer coisa em seu diretório atual.
Atualização : O Docker agora permite ter o Dockerfile fora do contexto de compilação (corrigido em 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Então você também pode fazer algo como
fonte
dockerfile:
propriedade nabuild:
seção no arquivo Compose docs.docker.com/compose/compose-file/#/compose-file-referenceADD
um arquivo que esteja fora do diretório de contexto? É isso que estou tentando fazer, mas não acho que o uso-f
torne os arquivos externos adicionáveis.build: context: .., dockerfile: dir/Dockerfile
. Agora meu contexto de construção é o diretório pai!Costumo encontrar-me utilizando a
--build-arg
opção para esse fim. Por exemplo, depois de colocar o seguinte no Dockerfile:Você pode apenas fazer:
Mas observe o seguinte aviso na documentação do Docker :
Aviso: Não é recomendável usar variáveis em tempo de construção para transmitir segredos, como chaves do github, credenciais do usuário etc. Os valores das variáveis em tempo de construção são visíveis para qualquer usuário da imagem com o comando docker history.
fonte
No Linux, você pode montar outros diretórios em vez de simbolizá-los
Consulte /superuser/842642 para obter mais detalhes.
Não sei se algo semelhante está disponível para outros sistemas operacionais. Também tentei usar o Samba para compartilhar uma pasta e remontá-la no contexto do Docker, que também funcionou.
fonte
Passei um bom tempo tentando descobrir um bom padrão e como explicar melhor o que está acontecendo com esse suporte a recursos. Percebi que a melhor maneira de explicar era a seguinte ...
Então, com isso dito, aqui está um exemplo do Dockerfile que precisa reutilizar um arquivo chamado
start.sh
Dockerfile
Ele
ALWAYS
será carregado a partir de seu caminho relativo, tendo o próprio diretório atual comolocal
referência aos caminhos que você especificar.arquivos
Considerando essa idéia, podemos pensar em ter várias cópias para os Dockerfiles criando coisas específicas, mas todas elas precisam de acesso ao
start.sh
.Considerando essa estrutura e os arquivos acima, aqui está um docker-compose.yml
docker-compose.yaml
shared
diretório de contexto é oruntime
diretóriocontext
.dockerfile
.O
docker-compose.yml
é o seguinteall-service
é definido como o contexto, o arquivo compartilhadostart.sh
é copiado para lá e o Dockerfile especificado por cada umdockerfile
.Felicidades!
fonte
a/b/c
, então sim correndodocker build .
emc
não lhe permitirá o acesso../file-in-b
. Mas acho que o entendimento geral geral nisto (ou pelo menos o meu era) é que o contexto é definido pelo local indicado pelo primeiro argumento do comando build, não pelo local do Dockerfile. Portanto, conforme declarado na resposta aceita: froma
:docker build -f a/b/c/Dockerfile .
significa que agora no Dockerfile.
está a pastaa
Se você ler a discussão no problema 2745, não apenas o docker poderá suportar links simbólicos, mas também a adição de arquivos fora do seu contexto. Parece ser uma filosofia de design que os arquivos que entram na construção do Docker devem explicitamente fazer parte de seu contexto ou pertencer a uma URL na qual é presumivelmente implantada também com uma versão fixa, para que a construção possa ser repetida com URLs ou arquivos conhecidos fornecidos com o container docker.
Apenas minha opinião, mas acho que você deve se reestruturar para separar os repositórios de código e docker. Dessa forma, os contêineres podem ser genéricos e extrair qualquer versão do código no tempo de execução, em vez do tempo de compilação.
Como alternativa, use o docker como seu artefato de implantação de código fundamental e, em seguida, coloque o arquivo docker na raiz do repositório de códigos. se você seguir essa rota, provavelmente faz sentido ter um contêiner de janela de encaixe pai para obter detalhes mais gerais do nível do sistema e um contêiner filho para configuração específica ao seu código.
fonte
Acredito que a solução mais simples seria alterar o próprio 'contexto'.
Então, por exemplo, em vez de dar:
que define o diretório atual como o contexto, digamos que você queira o diretório pai como contexto, basta usar:
fonte
make build
e ele puxa todos os arquivos necessários se eles foram atualizados e, em seguida, chama a construção apropriada da docker ... Preciso fazer um trabalho extra, mas funciona perfeitamente porque estou no controle total.Você também pode criar um tarball do que a imagem precisa primeiro e usar isso como seu contexto.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
fonte
tar zc /dir1 /dir2 |docker build -
. Isso foi muito útil no meu caso.Usando o docker-compose, consegui isso criando um serviço que monta os volumes necessários e confirmando a imagem do contêiner. Em seguida, no serviço subseqüente, confio na imagem confirmada anteriormente, que possui todos os dados armazenados em locais montados. Você precisará copiar esses arquivos para o destino final, pois os diretórios montados no host não são confirmados ao executar um
docker commit
comandofonte
Eu tive esse mesmo problema em um projeto e em alguns arquivos de dados que não consegui mover dentro do contexto de repo por motivos HIPPA. Acabei usando 2 Dockerfiles. Um cria o aplicativo principal sem o material necessário fora do contêiner e o publica no repositório interno. Em seguida, um segundo arquivo docker extrai essa imagem e adiciona os dados e cria uma nova imagem que é implantada e nunca armazenada em nenhum lugar. Não é o ideal, mas funcionou para meus propósitos de manter informações confidenciais fora do repositório.
fonte
Uma solução fácil pode ser simplesmente montar o volume (usando o sinalizador -v ou --mount) no contêiner quando você o executa e acessa os arquivos dessa maneira.
exemplo:
para mais informações, consulte: https://docs.docker.com/storage/volumes/
fonte
docker run
é tarde demais.Como é descrito neste problema do GitHub, a compilação realmente acontece
/tmp/docker-12345
, portanto, um caminho relativo como../relative-add/some-file
é relativo a/tmp/docker-12345
. Seria, portanto, procurar/tmp/relative-add/some-file
, o que também é mostrado na mensagem de erro. *Não é permitido incluir arquivos fora do diretório de compilação, portanto, isso resulta na mensagem "Caminho Proibido". "
fonte
Uma maneira rápida e suja é configurar o contexto da construção em quantos níveis você precisar - mas isso pode ter consequências. Se você estiver trabalhando em uma arquitetura de microsserviços assim:
Você pode definir o contexto de construção para o pai
Code
diretório e acessar tudo, mas acontece que, com um grande número de repositórios, isso pode resultar em um longo período de construção.Um exemplo de situação pode ser que outra equipe mantenha um esquema de banco de dados
Repo1
e o código da sua equipe emRepo2
depender disso. Você deseja dockerizar essa dependência com alguns de seus próprios dados iniciais, sem se preocupar com alterações de esquema ou poluir o repositório da outra equipe (dependendo de quais são as alterações, você ainda poderá alterar seus scripts de dados iniciais). A segunda abordagem é hacky, mas contorna a questão das compilações longas:Crie um script sh (ou ps1)
./Code/Repo2
para copiar os arquivos necessários e chamar os comandos do docker que você deseja, por exemplo:No arquivo docker-compose, basta definir o contexto como
Repo2
raiz e usar o conteúdo do./db/schema
diretório em seu dockerfile sem se preocupar com o caminho. Lembre-se de que você corre o risco de comprometer acidentalmente esse diretório para o controle de origem, mas as ações de limpeza de script devem ser fáceis o suficiente.fonte
No meu caso, meu Dockerfile é escrito como um modelo contendo espaços reservados que estou substituindo por valor real usando meu arquivo de configuração.
Portanto, não pude especificar esse arquivo diretamente, mas inseri-lo na construção do docker da seguinte maneira:
Mas por causa do tubo, o
COPY
comando não funcionou. Mas a maneira acima resolve isso-f -
(explicitamente dizendo que o arquivo não é fornecido). Fazendo apenas-
sem a-f
bandeira, o contexto E o Dockerfile não são fornecidos, o que é uma ressalva.fonte
O truque é reconhecer que você pode especificar o contexto no comando build para incluir arquivos do diretório pai, se você especificar o caminho do Docker, eu mudaria meu Dockerfile para ficar assim:
Então meu comando build pode ficar assim:
No diretório do projeto
Do projeto / janela de encaixe
fonte