Eu tenho um aplicativo que executa várias coisas divertidas com o Git (como executar o git clone e git push) e estou tentando encaixá-lo.
Estou enfrentando um problema, no qual preciso adicionar uma chave SSH ao contêiner para o usuário 'contêiner' usar.
Tentei copiá-lo /root/.ssh/
, mudar $HOME
, criar um invólucro git ssh, e ainda sem sorte.
Aqui está o Dockerfile para referência:
#DOCKER-VERSION 0.3.4
from ubuntu:12.04
RUN apt-get update
RUN apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install nodejs -y
ADD . /src
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
RUN cd /src; npm install
EXPOSE 808:808
CMD [ "node", "/src/app.js"]
app.js
executa os comandos git como git pull
Respostas:
É um problema mais difícil se você precisar usar o SSH no momento da construção. Por exemplo, se você estiver usando
git clone
, ou no meu caso,pip
enpm
baixar de um repositório particular.A solução que encontrei é adicionar suas chaves usando a
--build-arg
bandeira. Em seguida, você pode usar o novo--squash
comando experimental (adicionado 1.13) para mesclar as camadas para que as chaves não fiquem mais disponíveis após a remoção. Aqui está a minha solução:Comando Build
Dockerfile
Atualização: se você estiver usando o Docker 1.13 e tiver recursos experimentais, poderá anexar
--squash
ao comando build que mesclará as camadas, removendo as chaves SSH e ocultando-asdocker history
.fonte
id_rsa.pub
arquivo, pois não é necessário.$(openssl rsa -in ~/.ssh/id_rsa)
vezAcontece que ao usar o Ubuntu, o ssh_config não está correto. Você precisa adicionar
ao seu Dockerfile para que ele reconheça sua chave ssh.
fonte
RUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
A chave ssh permanece armazenada na imagem, mesmo se você remover a chave em um comando de camada depois de adicioná-la (consulte os comentários nesta postagem ).
No meu caso, está tudo bem, então é isso que estou usando:
fonte
Se você estiver usando o docker composer, uma escolha fácil é encaminhar o agente SSH assim:
fonte
SSH_AUTH_SOCK
é uma variável, que contém um caminho para um ssh-agenteSSH_AUTH_SOCK
blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add$SSH_AUTH_SOCK
, você deve montá-lo -/run/host-services/ssh-auth.sock
.Expandindo a resposta de Peter Grainger, eu pude usar a compilação de vários estágios disponível desde o Docker 17.05. Página oficial afirma:
Mantendo isso em mente aqui é o meu exemplo de
Dockerfile
inclusão de três estágios de construção. Ele foi criado para criar uma imagem de produção do aplicativo Web cliente..dockerignore
repete o conteúdo do.gitignore
arquivo (impedenode_modules
que osdist
diretórios resultantes do projeto sejam copiados):Exemplo de comando para criar uma imagem:
Se sua chave SSH privada não tiver uma senha, basta especificar o
SSH_KEY_PASSPHRASE
argumento vazio .É assim que funciona:
1) Somente no primeiro estágio
package.json
, osyarn.lock
arquivos e a chave SSH privada são copiados para a primeira imagem intermediária denominadasources
. Para evitar mais solicitações de senha de chave SSH, ela é automaticamente adicionadassh-agent
. Finalmente, oyarn
comando instala todas as dependências necessárias do NPM e clona os repositórios git privados do Bitbucket sobre SSH.2) O segundo estágio cria e reduz o código fonte do aplicativo Web e o coloca no
dist
diretório da próxima imagem intermediária denominadaproduction
. Observe que o código fonte do instaladonode_modules
é copiado da imagem nomeadasources
produzida no primeiro estágio por esta linha:Provavelmente também poderia ser a seguinte linha:
Temos apenas o
node_modules
diretório da primeira imagem intermediária aqui, nãoSSH_KEY
eSSH_KEY_PASSPHRASE
mais argumentos. Todo o restante necessário para a construção é copiado do diretório do projeto.3) No terceiro estágio, reduzimos o tamanho da imagem final que será marcada,
ezze/geoport:0.6.0
incluindo apenas odist
diretório da segunda imagem intermediária denominadaproduction
e instalando o Node Express para iniciar um servidor da web.A listagem de imagens fornece uma saída como esta:
onde imagens sem etiqueta correspondem aos primeiro e segundo estágios de construção intermediários.
Se você correr
você não verá nenhuma menção de
SSH_KEY
eSSH_KEY_PASSPHRASE
na imagem final.fonte
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
mas quando eu verifico outro RUN ou mesmo no mesmo RUN comando ao fazer umssh-add -l
, diz-me que "O agente não tem identidades". Começando a arrancar meus cabelos, algum pensamento?Para injetar sua chave ssh, em um contêiner, você tem várias soluções:
Usando um Dockerfile com a
ADD
instrução, você pode injetá-lo durante o processo de compilaçãoSimplesmente fazendo algo como
cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'
Usando o
docker cp
comando que permite injetar arquivos enquanto um contêiner está em execução.fonte
apt-get install openssh-server
e colocando minha chave em /root/.ssh/id_rsa e funcionou bem. Qual imagem você está usando?Uma solução de plataforma cruzada é usar uma montagem de ligação para compartilhar a
.ssh
pasta do host no contêiner:Semelhante ao encaminhamento do agente, essa abordagem tornará as chaves públicas acessíveis ao contêiner. Uma vantagem adicional é que ele também funciona com um usuário não root e o conectará ao GitHub. Uma ressalva a considerar, no entanto, é que todo o conteúdo (incluindo chaves privadas) da
.ssh
pasta será compartilhado, portanto essa abordagem é apenas desejável para o desenvolvimento e apenas para imagens de contêineres confiáveis.fonte
docker build
apenas durantedocker run
docker-compose up
no Windows 10. local. Como devo usar sua solução nesse cenário?Os contêineres do Docker devem ser vistos como 'serviços' próprios. Para separar preocupações, você deve separar as funcionalidades:
1) Os dados devem estar em um contêiner de dados: use um volume vinculado para clonar o repositório. Esse contêiner de dados pode ser vinculado ao serviço que precisa dele.
2) Use um contêiner para executar a tarefa de clonagem git (ou seja, é apenas o trabalho que está clonando) vinculando o contêiner de dados a ele quando você o executar.
3) O mesmo para a chave ssh: coloque um volume (como sugerido acima) e vincule-o ao serviço de clone do git quando você precisar
Dessa forma, a tarefa de clonagem e a chave são efêmeras e ativas apenas quando necessário.
Agora, se o aplicativo em si for uma interface git, convém considerar as APIs REST do github ou bitbucket diretamente para fazer seu trabalho: é para isso que elas foram projetadas.
fonte
Esta linha é um problema:
Ao especificar os arquivos que você deseja copiar para a imagem, você só pode usar caminhos relativos - em relação ao diretório em que está o Dockerfile. Então você deve usar:
E coloque o arquivo id_rsa no mesmo diretório em que está o seu Dockerfile.
Verifique isso para obter mais detalhes: http://docs.docker.io/reference/builder/#add
fonte
docker cp
apenas coloca no container e não na imagem, certo?Tivemos um problema semelhante ao fazer a instalação do npm no tempo de construção do docker.
Inspirados na solução de Daniel van Flymen e combinando-a com a reescrita de git url , descobrimos um método um pouco mais simples para autenticar a instalação do npm a partir de repositórios particulares do github - usamos tokens oauth2 em vez das chaves.
No nosso caso, as dependências do npm foram especificadas como "git + https://github.com/ ..."
Para autenticação no contêiner, os URLs precisam ser reescritos para serem adequados para autenticação ssh (ssh: //[email protected]/) ou autenticação de token (https: // $ {GITHUB_TOKEN} @ github.com /)
Comando Build:
Infelizmente, estou no docker 1.9, então a opção --squash ainda não está lá, eventualmente ela precisa ser adicionada
Dockerfile:
fonte
Encaminhe o soquete de autenticação ssh para o contêiner:
Seu script poderá executar a
git clone
.Extra: se você deseja que os arquivos clonados pertençam a um usuário específico, é necessário usar,
chown
pois o uso de outro usuário que não seja root dentro do contêiner fará com quegit
falhe.Você pode fazer esta publicação no ambiente do contêiner algumas variáveis adicionais:
Depois de clonar, você deve executar
chown $OWNER_USER:$OWNER_GROUP -R <source_folder>
para definir a propriedade adequada antes de sair do contêiner, para que os arquivos sejam acessíveis por um usuário não raiz fora do contêiner.fonte
-u root:$(id -u $USER)
para pelo menos os arquivos pertencentes ao mesmo grupo principal que o usuário, o que deve tornar todos eles pelo menos legíveis, a menossudo
que algo os esteja criando com0600
permissões.-u root:$(id -u $USER)
deveria ser-g
./tmp/ssh_auth.sock: No such file or directory
agora está/tmp/ssh-vid8Zzi8UILE/agent.46016
na minha máquina host/tmp
dentro de seu contêiner. Ou um erro de digitação no comando docker run. Verifique se a instrução de ligação está correta-v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock
: Ordem é importante e ponto-e-vírgula também é importante. Verifique a documentação do docker para obter mais ajuda.Como o eczajk já comentou na resposta de Daniel van Flymen, não parece seguro remover as chaves e usá-las
--squash
, pois elas ainda serão visíveis na história (docker history --no-trunc
).Em vez disso, com o Docker 18.09, agora você pode usar o recurso "construir segredos". No meu caso, clonei um repositório Git privado usando a chave SSH dos meus hosts com o seguinte no meu Dockerfile:
Para poder usar isso, é necessário ativar o novo back-end BuildKit antes da execução
docker build
:E você precisa adicionar o
--ssh default
parâmetro paradocker build
.Mais informações sobre isso aqui: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
fonte
ssh-add ~/.ssh/id_rsa
e 2) Adicionar o anfitrião git para known_hosts, ou seja, para bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.
apesar de passar a--ssh default
bandeira na minha janela de encaixe e usar--mount=type=ssh
o comando run em que eugit clone
. Sou capaz de clonar o mesmo repositório sem problemas na máquina de compilação. Simplesmente falha no contêiner de construção da janela de encaixe. Eu suspeito que a versão para mac do Docker não esteja realmente transmitindo o cliente ssh.Esta questão é realmente irritante. Como você não pode adicionar / copiar nenhum arquivo fora do contexto do dockerfile, isso significa que é impossível vincular ~ / .ssh / id_rsa ao /root/.ssh/id_rsa da imagem e quando você definitivamente precisa de uma chave para executar alguma coisa de sshed como o git clone de um link de repo privado ..., durante a construção da sua imagem do docker.
Enfim, encontrei uma solução para a solução alternativa, não tão convincente, mas funcionou para mim.
no seu arquivo docker:
um script para fazer em uma sessão:
sempre que você precisar executar um contêiner a partir desta imagem com alguns requisitos ssh, basta adicionar -v para o comando run, como:
docker execute -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa --name comando imagem de contêiner
Essa solução não resulta em nenhuma chave privada na imagem do docker e na imagem do docker, portanto, não há mais problema de segurança com o que se preocupar.
fonte
docker cp
? É usado para "Copiar arquivos / pastas entre um contêiner e seu host".docker cp
poderia fazer o truque. No entanto, nessa mesma situação, eu precisava da ssh_key durante a criação da imagem, e não há nenhum contêiner naquele momento ... atualizará minha expressão pouco clara, obrigado de qualquer maneira.Encontrei o mesmo problema hoje e uma versão modificada com posts anteriores achei essa abordagem mais útil para mim
(Observe que o sinalizador somente leitura para que o contêiner não mexa na minha chave ssh em nenhum caso.)
Agora, dentro do contêiner, posso executar:
Portanto, não recebo o
Bad owner or permissions on /root/.ssh/..
erro que foi observado por @krossfonte
ssh-agent bash -c "ssh-add..."
. Posso então passar isso direto para a janela de encaixe. Todos os exemplos anteriores que encontrei foram utilizadoseval ssh-agent
, seguidos por ssh-add e não consegui descobrir uma maneira de passar issoeval
pelo comando docker run.'você pode permitir seletivamente que os servidores remotos acessem seu agente ssh local como se estivesse em execução no servidor'
https://developer.github.com/guides/using-ssh-agent-forwarding/
fonte
Você também pode vincular seu diretório .ssh entre o host e o contêiner. Não sei se esse método tem implicações de segurança, mas pode ser o método mais fácil. Algo assim deve funcionar:
Lembre-se de que a janela de encaixe é executada com o sudo (a menos que você não faça isso), se esse for o caso, você usará as teclas ssh raiz.
fonte
Bad owner or permissions on /root/.ssh/config
.docker run
, mas não durantedocker build
.A partir de
docker API 1.39+
(Verificar versão da API comdocker version
) docker build permite a--ssh
opção com um soquete ou chaves de agente para permitir que o Docker Engine encaminhe as conexões do agente SSH.Comando Build
Dockerfile
Mais informações:
fonte
could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory
. Use o caminho completo se não funcionar.Se você não se importa com a segurança de suas chaves SSH, há muitas boas respostas aqui. Em caso afirmativo, a melhor resposta que encontrei foi de um link no comentário acima para este comentário do GitHub por diegocsandrim . Para que outros tenham maior probabilidade de vê-lo, e no caso de esse repositório desaparecer, aqui está uma versão editada dessa resposta:
A maioria das soluções aqui acaba deixando a chave privada na imagem. Isso é ruim, pois qualquer pessoa com acesso à imagem tem acesso à sua chave privada. Como não sabemos o suficiente sobre o comportamento de
squash
, isso ainda pode ser o caso, mesmo se você excluir a chave e esmagar essa camada.Geramos uma URL de pré-assinatura para acessar a chave com o aws s3 cli e limitamos o acesso por cerca de 5 minutos, salvamos essa URL de pré-assinatura em um arquivo no diretório repo e, em dockerfile, a adicionamos à imagem.
No dockerfile, temos um comando RUN que executa todas estas etapas: use a URL de pré-gravação para obter a chave ssh, execute o npm install e remova a chave ssh.
Ao fazer isso em um único comando, a chave ssh não seria armazenada em nenhuma camada, mas a URL de pré-assinatura será armazenada, e isso não é um problema, porque a URL não será válida após 5 minutos.
O script de construção se parece com:
O Dockerfile fica assim:
fonte
Nas versões posteriores do docker (17.05), você pode usar construções de vários estágios . Qual é a opção mais segura, pois as compilações anteriores só podem ser usadas pela compilação subsequente e são destruídas
Veja a resposta à minha pergunta sobre o stackoverflow para obter mais informações
fonte
Uma visão geral concisa dos desafios do SSH nos contêineres do Docker é detalhada aqui . Para conectar-se a controles remotos confiáveis a partir de um contêiner sem vazar segredos, existem algumas maneiras:
~/.ssh
ao contêiner. (Somente desenvolvimento, potencialmente inseguro)Além desses, há também a possibilidade de usar um armazenamento de chaves em execução em um contêiner de docker separado, acessível em tempo de execução ao usar o Compose. A desvantagem aqui é a complexidade adicional devido ao mecanismo necessário para criar e gerenciar um keystore, como o Vault da HashiCorp .
Para uso da chave SSH em um contêiner do Docker independente, consulte os métodos vinculados acima e considere as desvantagens de cada um, dependendo de suas necessidades específicas. Se, no entanto, você estiver executando o Compose e quiser compartilhar uma chave para um aplicativo em tempo de execução (refletindo os aspectos práticos do OP), tente o seguinte:
docker-compose.env
arquivo e adicione-o ao seu.gitignore
arquivo.docker-compose.yml
e adicione oenv_file
serviço que requer a chave.process.node.DEPLOYER_RSA_PUBKEY
no caso de um aplicativo Node.js.A abordagem acima é ideal para desenvolvimento e teste e, embora possa atender aos requisitos de produção, na produção é melhor usar um dos outros métodos identificados acima.
Recursos adicionais:
fonte
Você pode usar a construção de vários estágios para construir contêineres É a abordagem que você pode seguir: -
Estágio 1: construindo uma imagem com ssh
Etapa 2: construa seu contêiner
adicione o atributo env no seu arquivo de composição:
depois passe argumentos do script de construção como este:
E remova o contêiner intermediário por segurança. Isso irá ajudá-lo a aplausos.
fonte
Uma maneira simples e segura de conseguir isso sem salvar sua chave em uma camada de imagem do Docker ou passar pela ginástica ssh_agent é:
Como uma das etapas no seu
Dockerfile
, crie um.ssh
diretório adicionando:RUN mkdir -p /root/.ssh
Abaixo disso, indique que você deseja montar o diretório ssh como um volume:
VOLUME [ "/root/.ssh" ]
Verifique se o contêiner
ssh_config
sabe onde encontrar as chaves públicas adicionando esta linha:RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
Exponha o
.ssh
diretório do usuário local ao contêiner em tempo de execução:docker run -v ~/.ssh:/root/.ssh -it image_name
Ou
dockerCompose.yml
adicione-o na chave de volume do serviço:- "~/.ssh:/root/.ssh"
Sua final
Dockerfile
deve conter algo como:fonte
Estou tentando resolver o problema de outra maneira: adicionando a chave ssh pública a uma imagem. Mas, em meus testes, descobri que "docker cp" é para copiar de um contêiner para um host. O item 3 da resposta por creak parece estar dizendo que você pode usar o docker cp para injetar arquivos em um contêiner. Consulte https://docs.docker.com/engine/reference/commandline/cp/
excerto
fonte
Você pode passar as chaves autorizadas para o contêiner usando uma pasta compartilhada e definir permissões usando um arquivo docker como este:
E sua execução do docker contém algo como o seguinte para compartilhar um diretório de autenticação no host (segurando as teclas authorised_keys) com o contêiner e abrir a porta ssh que poderá ser acessada através da porta 7001 no host.
Você pode consultar https://github.com/jpetazzo/nsenter, que parece ser outra maneira de abrir um shell em um contêiner e executar comandos dentro de um contêiner.
fonte
É tardio para a parte, que tal isso, que disponibilizará as chaves do sistema operacional do host para fazer root dentro do contêiner, em tempo real:
Não sou a favor de usar o Dockerfile para instalar chaves, pois as iterações do seu contêiner podem deixar as chaves privadas para trás.
fonte
Eu estava tentando descobrir como adicionar chaves de assinatura a um contêiner para usar durante o tempo de execução (não compilar) e me deparei com essa pergunta. Os segredos do Docker parecem ser a solução para o meu caso de uso e, como ninguém o mencionou ainda, eu o adicionarei.
fonte
No meu caso, tive um problema com o nodejs e o 'npm i' de um repositório remoto. Corrigi-o adicionado usuário 'node' ao container nodejs e 700 ao ~ / .ssh no container.
Dockerfile:
run.sh:
docker-compose.yml:
depois disso começou a funcionar
fonte
De maneira mais simples, obtenha uma conta da barra de ativação e use: ssh-import-id
fonte
ssh-import-id
parece que apenas importa chaves públicas.Em um contêiner de docker em execução, você pode emitir ssh-keygen com a opção docker -i (interativa). Isso encaminhará as solicitações do contêiner para criar a chave dentro do contêiner do Docker.
fonte
Para debian / root / allowed_keys:
fonte