Usando chaves SSH dentro do contêiner de janela de encaixe


324

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


3
Qualquer pessoa que se aproxime dessa pergunta deve pensar no final do jogo, pois é fácil criar uma falha de segurança e esquecê-la aqui, se você não for cuidadoso. Leia todas as respostas e escolha sabiamente.
— Josh Habdas 17/09/19

Respostas:


144

É 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, pipe npmbaixar de um repositório particular.

A solução que encontrei é adicionar suas chaves usando a --build-argbandeira. Em seguida, você pode usar o novo --squashcomando 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

$ docker build -t example --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .

Dockerfile

FROM python:3.6-slim

ARG ssh_prv_key
ARG ssh_pub_key

RUN apt-get update && \
    apt-get install -y \
        git \
        openssh-server \
        libmysqlclient-dev

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
    chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa.pub

# Avoid cache purge by adding requirements first
ADD ./requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

# Remove SSH keys
RUN rm -rf /root/.ssh/

# Add the rest of the files
ADD . .

CMD python manage.py runserver

Atualização: se você estiver usando o Docker 1.13 e tiver recursos experimentais, poderá anexar --squashao comando build que mesclará as camadas, removendo as chaves SSH e ocultando-as docker history.


13
Esse encadeamento de problemas do GitHub indicaria que essa abordagem ainda não é segura. Veja este comentário para outra solução semelhante.
— eczajk

4
Outra solução, em vez de esmagar, é adicionar e remover a chave no mesmo comando RUN e, entre adicionar e remover, você a usa para o que precisa.
— Benjamin Hammer Nørgaard

2
Talvez você possa remover as linhas para criar o id_rsa.pubarquivo, pois não é necessário.
— LCB 9/11


Se a sua chave é protegido por senha, utilize $(openssl rsa -in ~/.ssh/id_rsa)vez
— BroiSatse

89

Acontece que ao usar o Ubuntu, o ssh_config não está correto. Você precisa adicionar

RUN  echo "    IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config

ao seu Dockerfile para que ele reconheça sua chave ssh.


2
Você provavelmente também precisa definir o nome de usuário correto como esteRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
— monofone

1
Por que alguém copiaria a chave privada de uma máquina host para um contêiner. Comando é OK, mas não vejo sentido em fazer do acima mencionado ...
— Vladimir Djuricic

12
Isso não é seguro! Veja minha solução abaixo para a versão 1.13 mais recente do Docker. @ebensing
— Daniel van Flymen

1
@VladimirDjuricic Existem coisas como chaves de implantação.
— Zelphir Kaltstahl

na verdade, você precisa executar o ssh-keygen -A para configurar o ssh corretamente no contêiner mínimo do ubuntu. Em seguida, você pode adicionar chaves pub / priv e iniciar o sshd. Eu tenho esta entrada no meu dockerfile: 'RUN ssh-keygen -A' como uma das etapas.
— Piotrektt 19/07/19

84

Nota : use esta abordagem apenas para imagens privadas e sempre serão !

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:

# Setup for ssh onto github
RUN mkdir -p /root/.ssh
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

91
Isso manterá sua chave na imagem, não faça isso.
— precisa saber é o seguinte

12
@CppLearner, você está certo, isso armazena a chave na imagem e isso pode ser um problema de segurança em alguns casos. Obrigado por destacar isso. No entanto, existem muitas situações em que isso é perfeitamente salvo. Por exemplo, para imagens armazenadas em um repositório privado ou imagens criadas diretamente em um servidor de produção, copiando as chaves locais para a imagem.
— yellowcap

2
Além disso, se você instalar seus fornecedores no Dockerfile, nada o impedirá de remover a chave ssh após a instalação dos fornecedores.
— SebScoFr

2
@SebScoFr, aparentemente as chaves serão armazenadas em uma das camadas, mesmo se você as remover em um comando posterior (consulte o link na resposta atualizada). Portanto, a imagem sempre expõe a chave ssh, e a solução deve ser usada apenas para imagens privadas!
— yellowcap

1
@yellowcap not if you --squash the build #
— 187 Anoyz

57

Se você estiver usando o docker composer, uma escolha fácil é encaminhar o agente SSH assim:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent

23
Apenas observe que isso não funciona para hosts Mac, seja usando docker-machine (via VirtualBox) ou Docker for Mac (que usa xhyve), porque os soquetes de domínio unix não estão em proxy.
— 21816 Joe Shaw

SSH_AUTH_SOCKé uma variável, que contém um caminho para um ssh-agente
— Aistis


1
Agora, o ssh-forwarding também é suportado nos hosts do macOS - em vez de montar o caminho $SSH_AUTH_SOCK, você deve montá-lo - /run/host-services/ssh-auth.sock.
— Jakub Kukul 22/03

47

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:

Com compilações de vários estágios, você usa várias FROMinstruções no Dockerfile. Cada FROMinstrução pode usar uma base diferente e cada uma delas inicia uma nova etapa da construção. Você pode copiar artefatos seletivamente de um estágio para outro, deixando para trás tudo o que não deseja na imagem final.

Mantendo isso em mente aqui é o meu exemplo de Dockerfileinclusão de três estágios de construção. Ele foi criado para criar uma imagem de produção do aplicativo Web cliente.

# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
    echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
    printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
    yarn --pure-lockfile --mutex file --network-concurrency 1 && \
    rm -rf /root/.ssh/

# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignorerepete o conteúdo do .gitignorearquivo (impede node_modulesque os distdiretórios resultantes do projeto sejam copiados):

.idea
dist
node_modules
*.log

Exemplo de comando para criar uma imagem:

$ docker build -t ezze/geoport:0.6.0 \
  --build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
  --build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
  ./

Se sua chave SSH privada não tiver uma senha, basta especificar o SSH_KEY_PASSPHRASEargumento vazio .

É assim que funciona:

1) Somente no primeiro estágio package.json, os yarn.lockarquivos e a chave SSH privada são copiados para a primeira imagem intermediária denominada sources. Para evitar mais solicitações de senha de chave SSH, ela é automaticamente adicionada ssh-agent. Finalmente, o yarncomando 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 distdiretório da próxima imagem intermediária denominada production. Observe que o código fonte do instalado node_modulesé copiado da imagem nomeada sourcesproduzida no primeiro estágio por esta linha:

COPY --from=sources /app/ /app/

Provavelmente também poderia ser a seguinte linha:

COPY --from=sources /app/node_modules/ /app/node_modules/

Temos apenas o node_modulesdiretório da primeira imagem intermediária aqui, não SSH_KEYe SSH_KEY_PASSPHRASEmais 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.0incluindo apenas o distdiretório da segunda imagem intermediária denominada productione instalando o Node Express para iniciar um servidor da web.

A listagem de imagens fornece uma saída como esta:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        3 hours ago         717MB
<none>              <none>              1f6518644324        3 hours ago         1.1GB
<none>              <none>              fa00f1182917        4 hours ago         1.63GB
node                carbon              b87c2ad8344d        4 weeks ago         676MB

onde imagens sem etiqueta correspondem aos primeiro e segundo estágios de construção intermediários.

Se você correr

$ docker history ezze/geoport:0.6.0 --no-trunc

você não verá nenhuma menção de SSH_KEYe SSH_KEY_PASSPHRASEna imagem final.


Post antigo, mas quero enfatizar que essa é de longe a melhor maneira de fazê-lo antes das 18.09. Squash é desnecessário e propenso a riscos. Com o estágio múltiplo, você sabe que está apenas trazendo os artefatos que deseja. Pense no squash como opt-out dos arquivos que você não deseja e em vários estágios como opt-in. Essa resposta precisa ser maior. Assar as teclas ssh na imagem é uma prática terrível.
— Mritalian

@ezze Muito obrigado por este post muito útil :) O agente SSH está me deixando louco, fiz algo parecido com o que você fez: eu vejo corretamente nos logs de construção do docker, Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)mas quando eu verifico outro RUN ou mesmo no mesmo RUN comando ao fazer um ssh-add -l, diz-me que "O agente não tem identidades". Começando a arrancar meus cabelos, algum pensamento?
— Alex

40

Para injetar sua chave ssh, em um contêiner, você tem várias soluções:

  1. Usando um Dockerfile com a ADDinstrução, você pode injetá-lo durante o processo de compilação

  2. Simplesmente fazendo algo como cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Usando o docker cpcomando que permite injetar arquivos enquanto um contêiner está em execução.


2
Então, a partir de agora, tentei copiá-lo para /root/.ssh/id_rsa, mas ainda recebi "Falha na verificação da chave do host. Fatal: a extremidade remota desligou inesperadamente" erros do Git, o que tenho certeza que significa não está usando a chave por qualquer motivo. Então, estou pensando que há outra coisa que preciso fazer para dizer ao sistema para usá-lo como chave ssh? Não sei exatamente como depurar este. (e eu sei que isso funciona chave porque ele é executado sem problema a partir do host)
— ebensing

você pode garantir que o / etc / ssh / ssh_config direcione o arquivo de chave correto?
— creack 8/08/13

1
Existe uma boa maneira de inspecionar os arquivos do contêiner de docker? Ou devo apenas tentar copiar em uma configuração válida?
— ebensing

3
Eu apenas tentei com a imagem 'base', fazendo apt-get install openssh-servere colocando minha chave em /root/.ssh/id_rsa e funcionou bem. Qual imagem você está usando?
— creack

se você precisar inspecionar o arquivo de um contêiner, a melhor maneira seria confirmar e executar a imagem resultante com 'cat'.
— creack

15

Uma solução de plataforma cruzada é usar uma montagem de ligação para compartilhar a .sshpasta do host no contêiner:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

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 .sshpasta será compartilhado, portanto essa abordagem é apenas desejável para o desenvolvimento e apenas para imagens de contêineres confiáveis.


1
isso pode funcionar, mas não docker buildapenas durantedocker run
— Alexander Mills

3
Esse é exatamente o ponto. Você não deseja colocar suas chaves ssh dentro de um arquivo docker.
— Mohammad Azim

2
Dado que o encaminhamento de agente SSH não funciona fora do Linux, isso é uma boa solução para a instalação e a execução em um ambiente de desenvolvimento sem muito barulho.
— Josh Habdas 26/09/19

Estou executando o Docker docker-compose upno Windows 10. local. Como devo usar sua solução nesse cenário?
— llaaalu 30/09/19

Essencialmente, você está perguntando como mapear o volume na composição do Docker. Acima, há uma resposta para responder a isso. Especificamente para o Windows, isso pode ajudar a stackoverflow.com/questions/41334021/…
— Mohammad Azim

14

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.


13

Esta linha é um problema:

ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa

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:

ADD id_rsa /root/.ssh/id_rsa

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


4
Isso também é um problema de segurança porque coloca uma chave privada em uma imagem que pode ser facilmente esquecida.
— Mike D

docker cpapenas coloca no container e não na imagem, certo?
— Alexander Mills

13

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: //git@github.com/) ou autenticação de token (https: // $ {GITHUB_TOKEN} @ github.com /)

Comando Build:

docker build -t sometag --build-arg GITHUB_TOKEN=$GITHUB_TOKEN . 

Infelizmente, estou no docker 1.9, então a opção --squash ainda não está lá, eventualmente ela precisa ser adicionada

Dockerfile:

FROM node:5.10.0

ARG GITHUB_TOKEN

#Install dependencies
COPY package.json ./

# add rewrite rule to authenticate github user
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

RUN npm install

# remove the secret token from the git config file, remember to use --squash option for docker build, when it becomes available in docker 1.13
RUN git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf

# Expose the ports that the app uses
EXPOSE 8000

#Copy server and client code
COPY server /server 
COPY clients /clients

11

Encaminhe o soquete de autenticação ssh para o contêiner:

docker run --rm -ti \
        -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock \
        -e SSH_AUTH_SOCK=/tmp/ssh_auth.sock \
        -w /src \
        my_image

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, chownpois o uso de outro usuário que não seja root dentro do contêiner fará com que gitfalhe.

Você pode fazer esta publicação no ambiente do contêiner algumas variáveis ​​adicionais:

docker run ...
        -e OWNER_USER=$(id -u) \
        -e OWNER_GROUP=$(id -g) \
        ...

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.


1
Nas versões mais recentes do Docker, você pode passar -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 menos sudoque algo os esteja criando com 0600permissões.
— dragon788

@ dragon788 Eu acho que você tem um erro de digitação: -u root:$(id -u $USER)deveria ser -g.
— edupo

Boa decisão! Parece que não consigo corrigi-lo a partir do celular, tentarei no desktop em breve.
— dragon788

Eu tenho /tmp/ssh_auth.sock: No such file or directoryagora está /tmp/ssh-vid8Zzi8UILE/agent.46016na minha máquina host
— vladkras

@vladkras o erro é bastante genérico. Pode ser causado devido a permissões /tmpdentro 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.
— edupo

10

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:

# syntax=docker/dockerfile:experimental

[...]

RUN --mount=type=ssh git clone [...]

[...]

Para poder usar isso, é necessário ativar o novo back-end BuildKit antes da execução docker build:

export DOCKER_BUILDKIT=1

E você precisa adicionar o --ssh defaultparâmetro para docker build.

Mais informações sobre isso aqui: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
Melhor solução IMHO. Eu tive que fazer mais duas coisas para fazê-lo funcionar: 1) Adicionar a minha chave privada para ssh-agente com ssh-add ~/.ssh/id_rsae 2) Adicionar o anfitrião git para known_hosts, ou seja, para bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
— Moritz Ringler

Não consegui fazer isso funcionar. Ainda estou recebendo erros de permissão: 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 defaultbandeira na minha janela de encaixe e usar --mount=type=ssho comando run em que eu git 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.
— PMende

@PMende você conseguiu descobrir esse problema mencionado porque também estou enfrentando o mesmo.
— Sadan A.

@SadanArshad Parece que atualmente esta funcionalidade é suportada apenas se você estiver executando o Docker a partir de uma máquina Linux. Não funciona se você estiver executando os comandos do Docker em um Mac (e provavelmente no Windows também, embora eu não possa confirmar).
— PMende

Pena que não funciona com o docker-compose ... github.com/docker/compose/issues/6440
— Alexis Wilke

9

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.

  1. no seu arquivo docker:

    • adicione este arquivo como /root/.ssh/id_rsa
    • faça o que quiser, como git clone, compositor ...
    • rm /root/.ssh/id_rsa no final
  2. um script para fazer em uma sessão:

    • cp sua chave para a pasta que contém o dockerfile
    • docker build
    • rm a chave copiada
  3. 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.


1
"Como você não pode adicionar / copiar nenhum arquivo fora do contexto do dockerfile," Você viu docker cp? É usado para "Copiar arquivos / pastas entre um contêiner e seu host".
— Jonathon Reinhart

@ JonathonReinhart, obrigado por apontar isso. Sim, docker cppoderia 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.
— ImLeo

9

Encontrei o mesmo problema hoje e uma versão modificada com posts anteriores achei essa abordagem mais útil para mim

docker run -it -v ~/.ssh/id_rsa:/root/.my-key:ro image /bin/bash

(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:

ssh-agent bash -c "ssh-add ~/.my-key; git clone <gitrepourl> <target>"

Portanto, não recebo o Bad owner or permissions on /root/.ssh/..erro que foi observado por @kross


Obrigado! Esta foi a chave para fazê-lo funcionar para mim: ter o ssh-agent e ssh-add em um único comando como: ssh-agent bash -c "ssh-add...". Posso então passar isso direto para a janela de encaixe. Todos os exemplos anteriores que encontrei foram utilizados eval ssh-agent, seguidos por ssh-add e não consegui descobrir uma maneira de passar isso evalpelo comando docker run.
— Ryanman


6

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:

$ sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash

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.


O uso desse método funciona com o docker 0.11, mas se você usar o fig, ocorrerá um erro de pânico. Não sei por que
— Luis Elizondo

3
Esse seria um método preferido, o truque seria usar as chaves do meu usuário host não privilegiado como raiz do contêiner. Como você mencionou, tentar fazê-lo não como o usuário root do host produz Bad owner or permissions on /root/.ssh/config.
— quer

isso só pode ser usado durante docker run, mas não durante docker build.
— Ccpizza #

3
@ccpizza, vejo isso como uma vantagem. Muitas dessas respostas deixam chaves privadas armazenadas em uma imagem; a chave permanece armazenada mesmo depois de removida a chave em um comando de camada subsequente. Ao introduzir as chaves privadas apenas durante a execução (não compilar), elas podem existir apenas no contêiner (não na imagem).
— cowlinator

6

A partir de docker API 1.39+(Verificar versão da API com docker version) docker build permite a --sshopção com um soquete ou chaves de agente para permitir que o Docker Engine encaminhe as conexões do agente SSH.

Comando Build

export DOCKER_BUILDKIT=1
docker build --ssh default=~/.ssh/id_rsa .

Dockerfile

# syntax=docker/dockerfile:experimental
FROM python:3.7

# Install ssh client (if required)
RUN apt-get update -qq
RUN apt-get install openssh-client -y

# Download public key for github.com
RUN --mount=type=ssh mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Clone private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

Mais informações:


1
A expansão til não funcionou para mim; Eu tenho: 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.
— slhck 24/01

3

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 desquash , 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:

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

O Dockerfile fica assim:

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no git@github.com || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

1
O problema com esta solução é que, como o pre_sign_url muda sempre, a instalação do npm não pode ser armazenada em cache, mesmo que não haja alteração no arquivo packages.json. É melhor para obter a chave na build.sh e defini-lo como um argumento de compilação para que ele não vai mudar a cada vez
— Iorque Yang


3

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:

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:

  • Crie um docker-compose.envarquivo e adicione-o ao seu .gitignorearquivo.
  • Atualize docker-compose.ymle adicione o env_fileserviço que requer a chave.
  • Acesse a chave pública do ambiente no tempo de execução do aplicativo, por exemplo, process.node.DEPLOYER_RSA_PUBKEYno 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:


3

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

FROM ubuntu as sshImage
LABEL stage=sshImage
ARG SSH_PRIVATE_KEY
WORKDIR /root/temp

RUN apt-get update && \
    apt-get install -y git npm 

RUN mkdir /root/.ssh/ &&\
    echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa &&\
    chmod 600 /root/.ssh/id_rsa &&\
    touch /root/.ssh/known_hosts &&\
    ssh-keyscan github.com >> /root/.ssh/known_hosts

COPY package*.json ./

RUN npm install

RUN cp -R node_modules prod_node_modules

Etapa 2: construa seu contêiner

FROM node:10-alpine

RUN mkdir -p /usr/app

WORKDIR /usr/app

COPY ./ ./

COPY --from=sshImage /root/temp/prod_node_modules ./node_modules

EXPOSE 3006

CMD ["npm", "run", "dev"] 

adicione o atributo env no seu arquivo de composição:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

depois passe argumentos do script de construção como este:

docker-compose build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"

E remova o contêiner intermediário por segurança. Isso irá ajudá-lo a aplausos.


2

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 é:

  1. Como uma das etapas no seu Dockerfile, crie um .sshdiretório adicionando:

    RUN mkdir -p /root/.ssh

  2. Abaixo disso, indique que você deseja montar o diretório ssh como um volume:

    VOLUME [ "/root/.ssh" ]

  3. Verifique se o contêiner ssh_configsabe onde encontrar as chaves públicas adicionando esta linha:

    RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

  4. Exponha o .sshdiretório do usuário local ao contêiner em tempo de execução:

    docker run -v ~/.ssh:/root/.ssh -it image_name

    Ou dockerCompose.ymladicione-o na chave de volume do serviço:

    - "~/.ssh:/root/.ssh"

Sua final Dockerfiledeve conter algo como:

FROM node:6.9.1

RUN mkdir -p /root/.ssh
RUN  echo "    IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

VOLUME [ "/root/.ssh" ]

EXPOSE 3000

CMD [ "launch" ]

1

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

Copie arquivos / pastas do sistema de arquivos de um contêiner para o caminho do host. Os caminhos são relativos à raiz do sistema de arquivos.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

Este URL parece estar quebrado agora.
— Slm 31/07

Isso é obsoleto ou incorreto. Pode copiar qualquer direção, a partir de 1.8.2.
— Jonathon Reinhart

1

Você pode passar as chaves autorizadas para o contêiner usando uma pasta compartilhada e definir permissões usando um arquivo docker como este:

FROM ubuntu:16.04
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
EXPOSE 22
RUN cp /root/auth/id_rsa.pub /root/.ssh/authorized_keys
RUN rm -f /root/auth
RUN chmod 700 /root/.ssh
RUN chmod 400 /root/.ssh/authorized_keys
RUN chown root. /root/.ssh/authorized_keys
CMD /usr/sbin/sshd -D

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.

-d -v /home/thatsme/dockerfiles/auth:/root/auth -–publish=127.0.0.1:7001:22

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.


1

É 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:

docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh user@10.20.30.40"

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.


0

Você pode usar segredos para gerenciar quaisquer dados confidenciais que um contêiner precisa em tempo de execução, mas não deseja armazenar na imagem ou no controle de origem, como:

  • Nomes de usuário e senhas
  • Certificados e chaves TLS
  • Chaves SSH
  • Outros dados importantes, como o nome de um banco de dados ou servidor interno
  • Sequências genéricas ou conteúdo binário (tamanho de até 500 kb)

https://docs.docker.com/engine/swarm/secrets/

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.


0

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:

USER node #added the part
COPY run.sh /usr/local/bin/
CMD ["run.sh"]

run.sh:

#!/bin/bash
chmod 700 -R ~/.ssh/; #added the part

docker-compose.yml:

nodejs:
      build: ./nodejs/10/
      container_name: nodejs
      restart: always
      ports:
        - "3000:3000"
      volumes:
        - ../www/:/var/www/html/:delegated
        - ./ssh:/home/node/.ssh #added the part
      links:
        - mailhog
      networks:
        - work-network

depois disso começou a funcionar


-1

De maneira mais simples, obtenha uma conta da barra de ativação e use: ssh-import-id


8
A questão era sobre chaves privadas. ssh-import-idparece que apenas importa chaves públicas.
— Cdd #

-1

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.


1
E depois o que? Você não pode fazer nada depois disso, porque não tem permissão para fazê-lo.
— Jonathon Reinhart

-1

Para debian / root / allowed_keys:

RUN set -x && apt-get install -y openssh-server

RUN mkdir /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN  echo "ssh-rsa AAAA....yP3w== rsa-key-project01" >> /root/.ssh/authorized_keys
RUN chmod -R go= /root/.ssh
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.