Klon pribadi git repo dengan dockerfile

240

Saya telah menyalin kode ini dari apa yang tampaknya merupakan berbagai dockerfiles yang bekerja di sekitar, ini milik saya:

FROM ubuntu

MAINTAINER Luke Crooks "[email protected]"

# 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 [email protected]:Pumalo/docker-conf.git /home/docker-conf

Ini memberi saya kesalahan

Step 10 : RUN git clone [email protected]: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 [email protected]:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128

Ini adalah pertama kalinya saya menggunakan dockerfiles, tetapi dari apa yang saya baca (dan diambil dari konfigurasi kerja) saya tidak bisa melihat mengapa ini tidak berhasil.

Id_rsa saya ada di folder yang sama dengan dockerfile saya dan merupakan salinan kunci lokal saya yang dapat mengkloning repo ini tanpa masalah.

Edit:

Di dockerfile saya, saya dapat menambahkan:

RUN cat /root/.ssh/id_rsa

Dan itu mencetak kunci yang benar, jadi saya tahu itu disalin dengan benar.

Saya juga telah berusaha melakukan apa yang disarankan oleh Nabi Nuh dan berlari:

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

Sayangnya ini juga tidak berhasil.

bajingan
sumber

Jawaban:

300

Kunci saya dilindungi kata sandi yang menyebabkan masalah, file yang berfungsi sekarang tercantum di bawah ini (untuk bantuan googler masa depan)

FROM ubuntu

MAINTAINER Luke Crooks "[email protected]"

# 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 [email protected]:User/repo.git
bajingan
sumber
11
Untuk jaga-jaga, ini adalah tautan yang menjelaskan cara menghapus perlindungan kata sandi kunci
Thomas
82
Hanya FYI, setelah Anda menjalankan RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts, Gambar akan menyimpannya sebagai layer. Jika ada yang menahan gambar Anda, mereka dapat mengambil kunci ... bahkan jika Anda menghapus file itu di lapisan selanjutnya, b / c mereka dapat kembali ke Langkah 7 ketika Anda menambahkannya.
Bernie Perez
23
Terima kasih atas jawabannya. Tetapi bagi kami bangunan gagal secara acak dan setelah penyelidikan kami perhatikan bahwa ssh-keyscanmemiliki batas waktu default 5 detik yang sering melebihi bitbucket. ssh-keyscanbahkan tidak akan melaporkan kesalahan. Jadi lebih baik lari RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hostsuntuk aman.
fluidsonic
5
Bisakah seseorang menjelaskan mengapa berlari ssh-keyscanitu masalah? Pemahaman saya adalah bahwa itu hanya akan menarik kunci publik dari Github / Bitbucket. Alternatif apa yang bisa digunakan sehingga tidak berakhir di lapisan?
Pedro
9
@Pedro Langkah keyscan khususnya bukan masalah sama sekali, Anda jelas benar. Jika ada, kunci publik host ini harus disebarkan sebanyak mungkin. Lihat sshd (8) untuk detail pada known_hostsfile. Orang-orang hanya membenarkan hal-hal acak ketika mereka terdengar cukup mengkhawatirkan.
mentega
99

Anda harus membuat kunci SSH baru yang ditetapkan untuk gambar Docker itu, karena Anda mungkin tidak ingin menanamkan kunci pribadi Anda di sana. Untuk membuatnya berfungsi, Anda harus menambahkan kunci itu ke kunci penempatan di repositori git Anda. Ini resep lengkapnya:

  1. Hasilkan kunci ssh dengan ssh-keygen -q -t rsa -N '' -f repo-keyyang akan memberi Anda file kunci-repo dan repo-key.pub.

  2. Tambahkan repo-key.pub ke kunci penyebaran repositori Anda.
    Pada GitHub, buka [repositori Anda] -> Pengaturan -> Sebarkan kunci

  3. Tambahkan sesuatu seperti ini ke Dockerfile Anda:

    Tambahkan kunci-repo /
    LARI \
      chmod 600 / kunci-repo && \  
      echo "IdentityFile / repo-key" >> / etc / ssh / ssh_config && \  
      echo -e "StrictHostKeyPeriksa no" >> / etc / ssh / ssh_config && \  
      // perintah git clone Anda di sini ...
    

Perhatikan bahwa di atas mematikan StrictHostKeyChecking, jadi Anda tidak perlu .ssh / known_hosts. Meskipun saya mungkin lebih suka solusi dengan ssh-keyscan di salah satu jawaban di atas.

Marcin R
sumber
6
Peringatan: pada konfigurasi saya, echo -e "..." juga menulis -e di dalam file. Hapus saja bendera dan itu berfungsi dengan baik.
Conchylicultor
Jawaban Anda sangat sempurna dalam membantu saya memecahkan masalah saya. Terima kasih!
David Pointer
Saya masih memiliki masalah yang sama:fatal: Could not read from remote repository.
Alex
1
Jutaan terima kasih! Saya siap menyatakan cinta kepada Anda. Anda memecahkan masalah yang saya perjuangkan selama berhari-hari!
alexandra
Jawaban yang dipilih untuk pertanyaan ini bukan jawaban yang baik lagi. Itu benar pada tahun 2014 tetapi untuk tahun 2020 ini adalah jawaban yang benar.
Bikal Basnet
70

Tidak perlu bermain-main dengan konfigurasi ssh. Gunakan file konfigurasi (bukan Dockerfile) yang berisi variabel lingkungan, dan minta skrip shell memperbarui file docker Anda saat runtime. Anda menjaga token dari Dockerfiles Anda dan Anda dapat mengkloning lebih dari https (tidak perlu menghasilkan atau melewati kunci ssh).

Buka Pengaturan> Token Akses Pribadi

  • Hasilkan token akses pribadi dengan reporuang lingkup diaktifkan.
  • Klon seperti ini: git clone https://[email protected]/user-or-org/repo

Beberapa komentator telah mencatat bahwa jika Anda menggunakan Dockerfile bersama, ini dapat mengekspos kunci akses Anda kepada orang lain di proyek Anda. Meskipun ini mungkin atau mungkin tidak menjadi perhatian untuk kasus penggunaan khusus Anda, berikut adalah beberapa cara Anda dapat mengatasinya:

  • Gunakan skrip shell untuk menerima argumen yang bisa berisi kunci Anda sebagai variabel. Ganti variabel di Dockerfile Anda dengan sedatau serupa, yaitu memanggil skrip sh rundocker.sh MYTOKEN=fooyang akan diganti https://{{MY_TOKEN}}@github.com/user-or-org/repo. Perhatikan bahwa Anda juga dapat menggunakan file konfigurasi (dalam format .yml atau apa pun yang Anda inginkan) untuk melakukan hal yang sama tetapi dengan variabel lingkungan.
  • Buat pengguna github (dan buat token akses untuk) hanya untuk proyek itu
Calvin Froedge
sumber
Untuk apa konteks yang Anda bicarakan Settings > Applications?
turboladen
1
Kelemahan dari pendekatan ini adalah bahwa Anda menyimpan kredensial untuk repo pribadi dalam Dockerfile sebagai lawan dari pendekatan @ crooksey yang akan memungkinkan Anda untuk referensi kunci yang disimpan secara terpisah dari Dockerfile. Tanpa konteks sekitar bagaimana OP menyimpan Dockerfile kami tidak dapat menentukan apakah ini akan menyebabkan masalah tetapi dari pengalaman pribadi saya ingin menyimpan Dockerfiles saya dalam VCS dan tidak ingin melakukan apa pun yang berisi kredensial. Setelah Docker menerapkan kemampuan untuk lulus variabel env untuk membangun perintah maka saya setuju ini akan menjadi solusi terbersih.
Jabbslad
2
@CalvinFroedge secara lokal Saya menganggap Anda maksud host Anda? Saya tidak mengetahui cara untuk mengekspos variabel lingkungan pada host ke wadah pada waktu build yang mengapa kami memiliki masalah terbuka seperti ini github.com/docker/docker/issues/6822 . Bisakah Anda menjelaskan?
Jabbslad
1
Bahkan lebih bersih (pemisahan kekhawatiran): volume tertaut untuk repo kloning + wadah khusus hanya untuk tugas kloning + volume tertaut hanya dengan kunci SSH (atau token, seperti yang Anda sarankan). Lihat stackoverflow.com/a/30992047 , mungkin dikombinasikan dengan stackoverflow.com/a/29981990 .
Peterino
9
Juga pertanyaannya adalah untuk repo BITBUCKET, bukan repo github.
Michael Draper
25

Pilihan lain adalah menggunakan multi-stage docker build untuk memastikan bahwa kunci SSH Anda tidak termasuk dalam gambar akhir.

Seperti yang dijelaskan dalam posting saya, Anda dapat menyiapkan gambar perantara Anda dengan dependensi yang diperlukan untuk mendapatkan clone dan kemudian COPYfile yang diperlukan ke dalam gambar akhir Anda.

Selain itu jika LABELkami lapisan menengah kami, kami bahkan dapat menghapusnya dari mesin setelah selesai.

# 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 [email protected]: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

Kita kemudian dapat membangun:

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

Buktikan kunci SSH kami hilang:

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

Bersihkan gambar setengah jadi dari mesin build:

docker rmi -f $(docker images -q --filter label=stage=intermediate)
jaker
sumber
ARG SSH_PRIVATE_KEY perlu diganti dengan ARG SSH_KEY
Joseph Persie
tidak bisakah kita menghapus kunci begitu git clone selesai?
Broncha,
1
Anda bisa melakukannya, tetapi Anda harus melakukannya sebagai bagian dari satu RUNsehingga Anda tidak meninggalkan kunci di lapisan gambar sebelumnya. Pada docker 1.13Anda dapat menggunakan argumen --squash eksperimental yang akan menghapus kunci SSH di lapisan gambar akhir Anda juga.
Jaker
19

Untuk repositori bitbucket, buat Sandi Aplikasi (pengaturan Bitbucket -> Manajemen Akses -> Sandi Aplikasi, lihat gambar) dengan akses baca ke repo dan proyek.

menu pengguna bitbucket

Maka perintah yang harus Anda gunakan adalah:

git clone https://username:[email protected]/reponame/projectname.git
Nominasi
sumber
1
Sederhana: Saya harus mengakui bahwa saya lebih suka pendekatan berbasis SSH, tetapi saya tidak bisa mendapatkan salah satu dari yang di atas berfungsi ... file tidak ditemukan, dll.
Janos
Saya tidak melihat "Manajemen Akses" ... Saya rasa ini sudah usang?
Martin Thoma
1
Bekerja! Polos dan sederhana ... Hebat!
Josemy
2
Tentu saja ... Anda hanya perlu mengklik gambar profil Anda di bar sebelah kiri, kemudian pada pengaturan Bitbucket dan Anda akan melihat sesuatu seperti ini: imgur.com/EI33zj3
Josemy
1
Ini berhasil untuk saya. Namun, saya punya submodules dan --recursivetidak berfungsi. Saya harus memasukkan git cloneuntuk setiap submodule, yang baik-baik saja tetapi akan lebih bagus jika itu akan bekerja secara rekursif.
Zailyn Tamayo
14

Anda sering tidak ingin melakukan git clonerepo pribadi dari dalam bangunan buruh pelabuhan. Melakukan klon di sana melibatkan menempatkan kredensial ssh pribadi di dalam gambar di mana mereka kemudian dapat diekstraksi oleh siapa pun dengan akses ke gambar Anda.

Sebagai gantinya, praktik umum adalah mengkloning git repo dari luar docker di alat CI pilihan Anda, dan cukup COPYfile ke dalam gambar. Ini memiliki manfaat kedua: caching buruh pelabuhan. Caching Docker melihat perintah yang sedang dijalankan, variabel lingkungan yang dicakupnya, memasukkan file, dll, dan jika mereka identik dengan build sebelumnya dari langkah induk yang sama, ia menggunakan kembali cache sebelumnya. Dengan sebuah git cloneperintah, perintah itu sendiri identik, jadi buruh pelabuhan akan menggunakan kembali cache meskipun repo git eksternal diubah. Namun, sebuah COPYperintah akan melihat file dalam konteks build dan dapat melihat apakah mereka identik atau telah diperbarui, dan menggunakan cache hanya ketika itu sesuai.


Jika Anda akan menambahkan kredensial ke dalam bangunan Anda, pertimbangkan untuk melakukannya dengan membangun multi-tahap, dan hanya menempatkan kredensial tersebut pada tahap awal yang tidak pernah ditandai dan didorong di luar host build Anda. Hasilnya terlihat seperti:

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 [email protected]:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <[email protected]>"

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

Baru-baru ini, BuildKit telah menguji beberapa fitur eksperimental yang memungkinkan Anda untuk meneruskan kunci ssh sebagai mount yang tidak pernah ditulis ke gambar:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <[email protected]>"

# 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 [email protected]:User/repo.git

Dan Anda dapat membangunnya dengan:

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

Perhatikan bahwa ini masih memerlukan kunci ssh Anda untuk tidak dilindungi kata sandi, tetapi Anda setidaknya dapat menjalankan build dalam satu tahap, menghapus perintah COPY, dan menghindari kredensial ssh agar tidak pernah menjadi bagian dari gambar.


BuildKit juga menambahkan fitur hanya untuk ssh yang memungkinkan Anda untuk tetap memiliki kunci ssh yang dilindungi kata sandi, hasilnya terlihat seperti:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <[email protected]>"

# 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 [email protected]:User/repo.git

Dan Anda dapat membangunnya dengan:

$ 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 .

Sekali lagi, ini disuntikkan ke dalam bangunan tanpa pernah ditulis ke lapisan gambar, menghilangkan risiko bahwa kredensial bisa bocor secara tidak sengaja.


Untuk memaksa buruh pelabuhan untuk menjalankan git clonebahkan ketika baris sebelumnya telah di-cache, Anda bisa menyuntikkan ARG build yang berubah dengan setiap build untuk memecahkan cache. Itu terlihat seperti:

# 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 [email protected]:User/repo.git

Kemudian Anda menyuntikkan itu mengubah arg di perintah membangun buruh pelabuhan:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .
BMitch
sumber
Anda menyarankan untuk menggunakan git dari luar Docker, namun Anda tetap menjelaskan cara menangani kunci ssh. Kapan Anda menganggap ini perlu / sesuai?
JCarlosR
2
@JCarlosR ketika Anda tidak memiliki sistem eksternal untuk menjalankan build (misalnya sistem CI / CD yang mampu menjalankan klon di muka). Mungkin ada pengecualian, tetapi klon di dalam Dockerfile adalah bau kode.
BMitch
1

Solusi di atas tidak bekerja untuk bitbucket. Saya pikir ini melakukan trik:

RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts \
    && eval `ssh-agent` \
    && ssh-add ~/.ssh/[key] \
    && git clone [email protected]:[team]/[repo].git
tvgriek
sumber