Clonare repository git privato con dockerfile


240

Ho copiato questo codice da quelli che sembrano essere vari dockerfile funzionanti, ecco il mio:

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git python-virtualenv

# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN chown -R root:root /root/.ssh

# Create known_hosts
RUN touch /root/.ssh/known_hosts

# Remove host checking
RUN echo "Host bitbucket.org\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf

Questo mi dà l'errore

Step 10 : RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf
 ---> Running in 0d244d812a54
Cloning into '/home/docker-conf'...
Warning: Permanently added 'bitbucket.org,131.103.20.167' (RSA) to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
2014/04/30 16:07:28 The command [/bin/sh -c git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128

Questa è la prima volta che utilizzo i file docker, ma da quello che ho letto (e tratto dalle configurazioni di lavoro) non riesco a capire perché questo non funziona.

Il mio id_rsa si trova nella stessa cartella del mio file docker ed è una copia della mia chiave locale che può clonare questo repository senza alcun problema.

Modificare:

Nel mio file docker posso aggiungere:

RUN cat /root/.ssh/id_rsa

E stampa la chiave corretta, quindi so che è stata copiata correttamente.

Ho anche provato a fare come consigliato da Noè e ho corso:

RUN echo "Host bitbucket.org\n\tIdentityFile /root/.ssh/id_rsa\n\tStrictHostKeyChecking no" >> /etc/ssh/ssh_config

Anche questo purtroppo non funziona.

Risposte:


300

La mia chiave era protetta da password che causava il problema, un file di lavoro è ora elencato di seguito (per aiuto di futuri googler)

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git
# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
ADD id_rsa /root/.ssh/id_rsa

# Create known_hosts
RUN touch /root/.ssh/known_hosts
# Add bitbuckets key
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

11
Per ogni evenienza, ecco un link che descrive come rimuovere la protezione con password della chiave
Thomas

82
Solo un FYI, dopo aver eseguito RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts, l'immagine lo salverà come layer. Se qualcuno ottiene una sospensione dell'immagine, può recuperare la chiave ... anche se elimini quel file in un livello successivo, in b / c può tornare al passaggio 7 quando l'hai aggiunto.
Bernie Perez,

23
Grazie per la risposta utile Ma per noi la compilazione è fallita casualmente e dopo un'indagine abbiamo notato che ssh-keyscanha un timeout predefinito di 5 secondi che bitbucket ha spesso superato. ssh-keyscannon segnalerà nemmeno un errore. Quindi correre meglio RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hostsper essere al sicuro.
fluidsonic,

5
Qualcuno potrebbe spiegare perché correre ssh-keyscanè un problema? La mia comprensione è che tirerà semplicemente la chiave pubblica di Github / Bitbucket. Quale alternativa può essere utilizzata in modo che non finisca in un livello?
Pedro,

9
@Pedro Il passaggio con i keyscan in particolare non è affatto un problema, hai chiaramente ragione. Semmai, queste chiavi pubbliche host dovrebbero essere diffuse il più possibile. Vedi sshd (8) per i dettagli sul known_hostsfile. Le persone semplicemente votano cose casuali quando sembrano abbastanza allarmanti.
TNE

99

È necessario creare un nuovo set di chiavi SSH per l'immagine Docker, poiché probabilmente non si desidera incorporare lì la propria chiave privata. Per farlo funzionare, dovrai aggiungere quella chiave alle chiavi di distribuzione nel tuo repository git. Ecco la ricetta completa:

  1. Genera i tasti ssh con i ssh-keygen -q -t rsa -N '' -f repo-keyquali riceverai i file repo-key e repo-key.pub.

  2. Aggiungi repo-key.pub alle chiavi di distribuzione del repository.
    Su GitHub, vai a [il tuo repository] -> Impostazioni -> Distribuisci chiavi

  3. Aggiungi qualcosa di simile al tuo Dockerfile:

    AGGIUNGI tasto repo /
    CORRERE \
      chmod 600 / repo-key && \  
      echo "IdentityFile / repo-key" >> / etc / ssh / ssh_config && \  
      echo -e "StrictHostKeyChecking no" >> / etc / ssh / ssh_config && \  
      // i tuoi comandi clone git qui ...
    

Si noti che sopra disattiva StrictHostKeyChecking, quindi non è necessario .ssh / known_hosts. Anche se probabilmente mi piace di più la soluzione con ssh-keyscan in una delle risposte sopra.


6
Attenzione: nella mia configurazione, echo -e "..." scrivi anche -e all'interno del file. Basta rimuovere la bandiera e funziona benissimo.
Conchylicultor,

La tua risposta è stata assolutamente perfetta per aiutarmi a risolvere il mio problema. Grazie!
David Pointer,

Ho ancora lo stesso problema:fatal: Could not read from remote repository.
Alex

1
Milioni di grazie! Sono sul punto di dichiararti amore. Hai risolto un problema che stavo combattendo da giorni!
alexandra,

La risposta selezionata per questa domanda non è più una buona risposta. Era corretto nel 2014, ma per il 2020 questa è la risposta corretta.
Bikal Basnet

70

Non è necessario giocherellare con le configurazioni ssh. Utilizzare un file di configurazione (non un file Docker) che contiene variabili di ambiente e fare in modo che uno script della shell aggiorni il file docker in fase di esecuzione. Tieni i token fuori dai tuoi Dockerfile e puoi clonare su https (non è necessario generare o passare chiavi ssh).

Vai su Impostazioni> Token di accesso personale

  • Generare un token di accesso personale con repoambito abilitato.
  • Clona in questo modo: git clone https://MY_TOKEN@github.com/user-or-org/repo

Alcuni commentatori hanno notato che se si utilizza un file Docker condiviso, ciò potrebbe esporre la chiave di accesso ad altre persone nel progetto. Sebbene questo possa o meno essere un problema per il tuo caso d'uso specifico, qui ci sono alcuni modi in cui puoi gestirlo:

  • Utilizzare uno script di shell per accettare argomenti che potrebbero contenere la chiave come variabile. Sostituisci una variabile nel tuo Dockerfile con sedo simile, ovvero chiamando lo script con il sh rundocker.sh MYTOKEN=fooquale si sostituirebbe https://{{MY_TOKEN}}@github.com/user-or-org/repo. Si noti che è anche possibile utilizzare un file di configurazione (in formato .yml o in qualsiasi formato desiderato) per fare la stessa cosa ma con variabili di ambiente.
  • Crea un utente github (e genera un token di accesso per) solo per quel progetto

Di quale contesto stai parlando Settings > Applications?
turboladen,

1
L'aspetto negativo di questo approccio è che si stanno memorizzando le credenziali per un repository privato all'interno del Dockerfile rispetto all'approccio di @ crooksey che consentirebbe di fare riferimento a una chiave memorizzata separatamente da un Dockerfile. Senza contesto sul modo in cui OP archivia il Dockerfile non possiamo determinare se ciò causerebbe un problema, ma per esperienza personale mi piace archiviare i miei Dockerfile in un VCS e non vorrei impegnare nulla che contenesse credenziali. Una volta che Docker implementa la capacità di passare le variabili env per creare il comando, sono d'accordo che questa sarebbe la soluzione più pulita.
Jabbslad,

2
@CalvinFroedge da localmente suppongo che intendi il tuo host? Non sono a conoscenza di un modo per esporre le variabili di ambiente sull'host in un contenitore in fase di compilazione, motivo per cui abbiamo problemi aperti come questo github.com/docker/docker/issues/6822 . Per favore, puoi chiarire?
Jabbslad,

1
Ancora più pulito (separazione delle preoccupazioni): un volume collegato per il repository clonato + un contenitore dedicato solo per l'attività di clonazione + un volume collegato solo con le chiavi SSH (o token, come suggerisci). Vedi stackoverflow.com/a/30992047 , magari combinato con stackoverflow.com/a/29981990 .
Peterino,

9
Anche la domanda è per un repository BITBUCKET, non un repository github.
Michael Draper,

25

Un'altra opzione è quella di utilizzare una build docker multi-stage per garantire che le chiavi SSH non siano incluse nell'immagine finale.

Come descritto nel mio post , puoi preparare la tua immagine intermedia con le dipendenze richieste per git clonare e quindi COPYi file richiesti nella tua immagine finale.

Inoltre, se abbiamo i LABELnostri strati intermedi, possiamo anche eliminarli dalla macchina al termine.

# Choose and name our temporary image.
FROM alpine as intermediate
# Add metadata identifying these images as our build containers (this will be useful later!)
LABEL stage=intermediate

# Take an SSH key as a build argument.
ARG SSH_KEY

# Install dependencies required to git clone.
RUN apk update && \
    apk add --update git && \
    apk add --update openssh

# 1. Create the SSH directory.
# 2. Populate the private key file.
# 3. Set the required permissions.
# 4. Add github to our list of known hosts for ssh.
RUN mkdir -p /root/.ssh/ && \
    echo "$SSH_KEY" > /root/.ssh/id_rsa && \
    chmod -R 600 /root/.ssh/ && \
    ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

# Clone a repository (my website in this case)
RUN git clone git@github.com:janakerman/janakerman.git

# Choose the base image for our final image
FROM alpine

# Copy across the files from our `intermediate` container
RUN mkdir files
COPY --from=intermediate /janakerman/README.md /files/README.md

Possiamo quindi costruire:

MY_KEY=$(cat ~/.ssh/id_rsa)
docker build --build-arg SSH_KEY="$MY_KEY" --tag clone-example .

Prova che le nostre chiavi SSH sono sparite:

docker run -ti --rm clone-example cat /root/.ssh/id_rsa

Pulisci immagini intermedie dalla macchina di costruzione:

docker rmi -f $(docker images -q --filter label=stage=intermediate)

ARG SSH_PRIVATE_KEY deve essere sostituito con ARG SSH_KEY
Joseph Persie,

non possiamo semplicemente eliminare le chiavi una volta che git clone è finito?
Broncha,

1
Potresti farlo, ma dovresti farlo come parte di un singolo in RUNmodo da non lasciare la chiave in un livello immagine precedente. A partire dalla finestra mobile 1.13è possibile utilizzare l' argomento --squash sperimentale che rimuove la chiave SSH anche nei livelli dell'immagine finale.
Jaker,

19

Per il repository bitbucket, genera la password dell'app (impostazioni Bitbucket -> Gestione degli accessi -> Password app, vedi l'immagine) con accesso in lettura al repository e al progetto.

menu utente bitbucket

Quindi il comando che dovresti usare è:

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git

1
Più semplice :) Devo ammettere che preferirei un approccio basato su SSH, ma non sono riuscito a far funzionare nessuno dei precedenti ... file non trovati, ecc.
Janos,

Non vedo "Gestione degli accessi" ... Immagino che sia obsoleto?
Martin Thoma,

1
Lavorato! Chiaro e semplice ... Fantastico!
Josemy,

2
Certo ... Devi solo fare clic sulla tua immagine del profilo sulla barra di sinistra, quindi sulle impostazioni di Bitbucket e vedrai qualcosa del genere: imgur.com/EI33zj3
Josemy

1
Questo ha funzionato per me. Tuttavia, ho sottomoduli e --recursivenon ha funzionato. Ho dovuto mettere git cloneper ogni sottomodulo, il che va bene, ma sarebbe stato fantastico se avrebbe funzionato in modo ricorsivo.
Zailyn Tamayo,

14

Spesso non si desidera eseguire un git clonerepository privato all'interno della build docker. Fare il clone lì implica posizionare le credenziali ssh private all'interno dell'immagine dove possono essere successivamente estratte da chiunque abbia accesso alla tua immagine.

Invece, la pratica comune è clonare il repository git dall'esterno della finestra mobile nello strumento di scelta rapida scelto e semplicemente COPYi file nell'immagine. Questo ha un secondo vantaggio: la memorizzazione nella finestra mobile. La memorizzazione nella cache Docker esamina il comando in esecuzione, le variabili di ambiente che include, i file di input, ecc. E se sono identici a una build precedente dallo stesso passaggio principale, riutilizza la cache precedente. Con un git clonecomando, il comando stesso è identico, quindi la finestra mobile riutilizza la cache anche se viene modificato il repository git esterno. Tuttavia, un COPYcomando esaminerà i file nel contesto di compilazione e potrà vedere se sono identici o se sono stati aggiornati e utilizzare la cache solo quando è appropriato.


Se hai intenzione di aggiungere credenziali alla tua build, prendi in considerazione la possibilità di farlo con una build multi-stage e ponendo solo quelle credenziali in una fase iniziale che non viene mai taggata e spinta all'esterno del tuo host di build. Il risultato è simile a:

FROM ubuntu as clone

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
COPY id_rsa /root/.ssh/id_rsa

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

COPY --from=clone /repo /repo
...

Più di recente, BuildKit ha testato alcune funzionalità sperimentali che consentono di passare una chiave ssh come mount che non viene mai scritto nell'immagine:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=secret,id=ssh_id,target=/root/.ssh/id_rsa \
    git clone git@bitbucket.org:User/repo.git

E puoi costruirlo con:

$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --secret id=ssh_id,src=$(pwd)/id_rsa .

Nota che questo richiede ancora che la tua chiave ssh non sia protetta da password, ma puoi almeno eseguire la build in una singola fase, rimuovendo un comando COPY ed evitando che le credenziali ssh facciano parte di un'immagine.


BuildKit ha anche aggiunto una funzione solo per ssh che ti consente di avere ancora le tue chiavi ssh protette da password, il risultato è simile:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=ssh \
    git clone git@bitbucket.org:User/repo.git

E puoi costruirlo con:

$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --ssh default=$SSH_AUTH_SOCK .

Ancora una volta, questo viene iniettato nella build senza mai essere scritto su un livello immagine, eliminando il rischio che la credenziale possa fuoriuscire accidentalmente.


Per forzare l'esecuzione della finestra mobile git cloneanche quando le linee precedenti sono state memorizzate nella cache, è possibile iniettare un ARG build che cambia con ogni build per interrompere la cache. Sembra che:

# inject a datestamp arg which is treated as an environment variable and
# will break the cache for the next RUN command
ARG DATE_STAMP
# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

Quindi si inietta quel cambio arg nel comando build docker:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .

Suggerisci di usare git dall'esterno di Docker, tuttavia spieghi comunque come gestire i tasti ssh. Quando lo ritieni necessario / appropriato?
JCarlosR,

2
@JCarlosR quando non si dispone di un sistema esterno in cui eseguire la build (ad esempio un sistema CI / CD in grado di eseguire il clone in anticipo). Possono esserci eccezioni, ma un clone all'interno di un file Docker è un odore di codice.
BMitch,

1

Le soluzioni precedenti non hanno funzionato per bitbucket. Ho pensato che questo fa il trucco:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone git@bitbucket.org:[team]/[repo].git
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.