Menggunakan kunci SSH di dalam wadah buruh pelabuhan

324

Saya memiliki aplikasi yang menjalankan berbagai hal menyenangkan dengan Git (seperti menjalankan git clone & git push) dan saya mencoba untuk merevisinya.

Saya mengalami masalah meskipun di mana saya harus dapat menambahkan kunci SSH ke wadah untuk 'pengguna' wadah untuk digunakan.

Saya mencoba menyalinnya ke dalam /root/.ssh/, mengubah $HOME, membuat bungkus git ssh, dan masih belum berhasil.

Berikut adalah Dockerfile untuk referensi:

#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 menjalankan perintah git like git pull

ebensing
sumber
3
Siapa pun yang mendekati pertanyaan ini harus memikirkan akhir permainan karena mudah untuk membuat lubang keamanan dan melupakannya di sini jika Anda tidak hati-hati. Baca semua jawaban dan pilih dengan bijak.
Josh Habdas

Jawaban:

144

Ini masalah yang lebih sulit jika Anda perlu menggunakan SSH saat membangun. Misalnya jika Anda menggunakan git clone, atau dalam kasus saya pipdan npmuntuk mengunduh dari repositori pribadi.

Solusi yang saya temukan adalah menambahkan kunci Anda menggunakan --build-argbendera. Kemudian Anda dapat menggunakan --squashperintah eksperimental baru (ditambahkan 1,13) untuk menggabungkan lapisan sehingga tombol tidak lagi tersedia setelah penghapusan. Inilah solusi saya:

Bangun perintah

$ 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

Pembaruan: Jika Anda menggunakan Docker 1.13 dan memiliki fitur eksperimental pada Anda dapat menambahkan --squashke perintah build yang akan menggabungkan lapisan, menghapus kunci SSH dan menyembunyikannya docker history.

Daniel van Flymen
sumber
13
Utas masalah GitHub ini akan menunjukkan bahwa pendekatan ini masih tidak aman. Lihat komentar ini untuk solusi serupa lainnya.
eczajk
4
Solusi lain daripada squashing adalah menambahkan dan menghapus kunci dalam perintah RUN yang sama, dan di antara menambah dan menghapus Anda menggunakannya untuk apa Anda membutuhkannya.
Benjamin Hammer Nørgaard
2
Mungkin Anda dapat menghapus baris untuk membuat id_rsa.pubfile karena tidak diperlukan.
LCB
1
Alih-alih meremasnya, gunakan build gambar multi-tahap .
Richard Kiefer
Jika kunci Anda dilindungi password, gunakan $(openssl rsa -in ~/.ssh/id_rsa)bukan
BroiSatse
89

Ternyata saat menggunakan Ubuntu, ssh_config tidak benar. Anda perlu menambahkan

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

ke Dockerfile Anda agar bisa mengenali kunci ssh Anda.

ebensing
sumber
2
Anda mungkin juga perlu mengatur nama pengguna yang benar seperti iniRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone
1
Mengapa seseorang menyalin kunci pribadi dari mesin host ke wadah. Perintah tidak apa-apa, tetapi saya tidak melihat akal dalam melakukan hal yang disebutkan di atas ...
Vladimir Djuricic
12
Ini tidak aman! Lihat solusi saya di bawah untuk versi 1.13 Docker terbaru. @ebensing
Daniel van Flymen
1
@VladimirDjuricic Ada beberapa hal seperti kunci penempatan.
Zelphir Kaltstahl
sebenarnya Anda perlu menjalankan ssh-keygen -A untuk mengatur ssh dengan benar di wadah minimal ubuntu. Kemudian Anda dapat menambahkan kunci pub / priv dan memulai sshd. Saya memiliki entri ini di dockerfile saya: 'RUN ssh-keygen -A' sebagai salah satu langkah.
piotrektt
84

Catatan : hanya gunakan pendekatan ini untuk gambar yang bersifat pribadi dan akan selalu !

Kunci ssh tetap tersimpan di dalam gambar, bahkan jika Anda menghapus kunci dalam perintah lapisan setelah menambahkannya (lihat komentar di posting ini ).

Dalam kasus saya ini tidak apa-apa, jadi ini yang saya gunakan:

# 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
yellowcap
sumber
91
Ini akan menjaga kunci Anda dalam gambar, jangan lakukan itu.
CppLearner
12
@ CppLearner Anda benar, ini memang menyimpan kunci dalam gambar, dan itu mungkin menjadi masalah keamanan dalam beberapa kasus. Terima kasih telah menyoroti itu. Namun, ada banyak situasi di mana ini sangat menyelamatkan. Misalnya untuk gambar yang disimpan dalam repositori pribadi, atau gambar yang dibangun langsung di server produksi yang menyalin kunci lokal ke gambar.
yellowcap
2
Juga, jika Anda menginstal vendor Anda di dalam Dockerfile, tidak ada yang menghentikan Anda dari menghapus kunci ssh setelah vendor diinstal.
SebScoFr
2
@SebScoFr, tampaknya kunci akan disimpan di salah satu layer, bahkan jika Anda menghapusnya di perintah selanjutnya (lihat tautan dalam jawaban yang diperbarui). Jadi gambar akan selalu memperlihatkan kunci ssh, dan solusinya hanya boleh digunakan untuk gambar pribadi!
yellowcap
1
@Yellowcap tidak jika Anda --squash the build
Anoyz
57

Jika Anda menggunakan buruh pelabuhan menulis pilihan mudah adalah untuk meneruskan agen SSH seperti itu:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent
Aistis
sumber
23
Hanya catatan bahwa ini tidak berfungsi untuk host Mac, apakah menggunakan mesin docker (via VirtualBox) atau Docker untuk Mac (yang menggunakan xhyve) karena soket domain unix tidak diproksi.
Joe Shaw
SSH_AUTH_SOCKadalah variabel, yang berisi path ke ssh-agent
Aistis
2
lebih detail tentang SSH_AUTH_SOCK blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add
JuanPablo
1
ssh-forwarding sekarang juga didukung pada host macOS - alih-alih memasang path $SSH_AUTH_SOCK, Anda harus me-mount path ini - /run/host-services/ssh-auth.sock.
Jakub Kukul
47

Memperluas jawaban Peter Grainger saya dapat menggunakan multi-stage build yang tersedia sejak Docker 17.05. Status halaman resmi:

Dengan pembuatan multi-tahap, Anda menggunakan beberapa FROMpernyataan di Dockerfile Anda. Setiap FROMinstruksi dapat menggunakan basis yang berbeda, dan masing-masing memulai tahap baru pembangunan. Anda dapat secara selektif menyalin artefak dari satu tahap ke tahap lainnya, meninggalkan semua yang tidak Anda inginkan dalam gambar akhir.

Ingatlah ini di sini adalah contoh saya Dockerfiletermasuk tiga tahap membangun. Ini dimaksudkan untuk membuat gambar produksi aplikasi web klien.

# 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"]

.dockerignoremengulangi isi .gitignorefile (mencegah node_modulesdan mengakibatkan distdirektori proyek tidak disalin):

.idea
dist
node_modules
*.log

Contoh perintah untuk membuat gambar:

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

Jika kunci SSH pribadi Anda tidak memiliki frasa sandi, cukup tentukan SSH_KEY_PASSPHRASEargumen kosong .

Begini Cara kerjanya:

1). Pada tahap pertama saja package.json, yarn.lockfile dan kunci SSH pribadi disalin ke gambar perantara pertama bernama sources. Untuk menghindari frasa sandi kunci SSH yang diminta, secara otomatis ditambahkan ssh-agent. Akhirnya yarnperintah menginstal semua dependensi yang diperlukan dari NPM dan klon repositori private git dari Bitbucket melalui SSH.

2). Tahap kedua membangun dan memperkecil kode sumber aplikasi web dan menempatkannya di distdirektori gambar perantara berikutnya bernama production. Perhatikan bahwa kode sumber yang diinstal node_modulesdisalin dari gambar bernama sourcesdiproduksi pada tahap pertama oleh baris ini:

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

Mungkin itu juga bisa menjadi baris berikut:

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

Kami hanya memiliki node_modulesdirektori dari gambar perantara pertama di sini, tidak ada SSH_KEYdan SSH_KEY_PASSPHRASEargumen lagi. Semua yang dibutuhkan untuk membangun disalin dari direktori proyek kami.

3). Pada tahap ketiga kami mengurangi ukuran gambar akhir yang akan ditandai sebagai ezze/geoport:0.6.0dengan hanya memasukkan distdirektori dari gambar perantara kedua bernama productiondan menginstal Node Express untuk memulai server web.

Listing gambar memberikan output seperti ini:

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

di mana gambar yang tidak di-tag terhubung ke tahap pembuatan lanjutan pertama dan kedua.

Jika Anda berlari

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

Anda tidak akan melihat menyebutkan dari SSH_KEYdan SSH_KEY_PASSPHRASEpada gambar akhir.

ezze
sumber
Posting lama, tapi saya ingin menekankan bahwa ini adalah cara terbaik untuk melakukannya sebelum 18.09. Squash tidak perlu, dan rawan risiko. Dengan multi-stage, Anda tahu Anda hanya membawa artefak yang Anda inginkan. Anggap squash sebagai menyisih dari file yang tidak Anda inginkan, dan multistage sebagai opt-in. Jawaban ini harus lebih tinggi. Memanggang kunci ssh Anda dalam gambar adalah praktik yang mengerikan.
mritalian
@ezze Terima kasih banyak untuk posting yang sangat berguna ini :) SSH-agent membuat saya gila, saya melakukan sesuatu yang mirip dengan yang Anda lakukan: Saya benar melihat di buruh pelabuhan membangun log Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)tetapi ketika saya memeriksa di RUN lain atau bahkan di RUN yang sama perintah dengan melakukan ssh-add -litu memberitahu saya bahwa "Agen tidak memiliki identitas". Mulai mencabut rambut saya, ada pikiran?
Alex
40

Untuk menyuntikkan kunci ssh Anda, dalam sebuah wadah, Anda memiliki beberapa solusi:

  1. Menggunakan Dockerfile dengan ADDinstruksi, Anda bisa menyuntikkannya selama proses build Anda

  2. Cukup melakukan sesuatu seperti cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Menggunakan docker cpperintah yang memungkinkan Anda untuk menyuntikkan file saat wadah sedang berjalan.

creack
sumber
2
Jadi, seperti yang sekarang, saya sudah mencoba menyalinnya ke /root/.ssh/id_rsa tetapi masih menerima "Verifikasi kunci host gagal. Fatal: Remote ujung menutup secara tak terduga" kesalahan dari Git, yang saya cukup yakin berarti itu tidak menggunakan kunci untuk alasan apa pun. Jadi saya berpikir ada hal lain yang perlu saya lakukan untuk benar-benar memberitahu sistem untuk menggunakannya karena itu kunci ssh? Tidak yakin persis bagaimana cara debug yang satu ini. (dan saya tahu kunci ini berfungsi karena berjalan tanpa masalah dari tuan rumah)
ebensing
dapatkah Anda memastikan / etc / ssh / ssh_config menargetkan file kunci yang benar?
creack
1
Apakah ada cara yang baik untuk memeriksa file buruh pelabuhan? Atau haruskah saya mencoba dan menyalin dalam konfigurasi yang valid?
ebensing
3
Saya baru saja mencoba dengan gambar 'base', melakukan apt-get install openssh-serverdan meletakkan kunci saya di /root/.ssh/id_rsa dan bekerja dengan baik. Gambar apa yang Anda gunakan?
creack
jika Anda perlu memeriksa file kontainer, cara terbaik adalah dengan mengkomit dan menjalankan gambar yang dihasilkan dengan 'cat'.
creack
15

Salah satu solusi lintas-platform adalah menggunakan bind mount untuk membagikan .sshfolder host ke kontainer:

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

Mirip dengan penerusan agen pendekatan ini akan membuat kunci publik dapat diakses oleh wadah. Sisi positif tambahannya adalah ia bekerja dengan pengguna non-root juga dan akan membuat Anda terhubung ke GitHub. Satu peringatan untuk dipertimbangkan, bagaimanapun, adalah bahwa semua konten (termasuk kunci pribadi) dari .sshfolder akan dibagikan sehingga pendekatan ini hanya diinginkan untuk pengembangan dan hanya untuk gambar kontainer tepercaya.

Mohammad Azim
sumber
1
ini mungkin berhasil, tetapi tidak docker buildhanya selamadocker run
Alexander Mills
3
Itulah intinya. Anda tidak ingin meletakkan kunci ssh di dalam file buruh pelabuhan.
Mohammad Azim
2
Mengingat penerusan agen SSH tidak berfungsi di luar Linux, ini membuat solusi yang baik untuk bangun dan berjalan di lingkungan pengembangan tanpa banyak keributan.
Josh Habdas
Saya menggunakan buruh pelabuhan docker-compose updi Windows 10. lokal saya. Bagaimana saya harus menggunakan solusi Anda dalam skenario itu?
llaaalu
Pada dasarnya Anda bertanya bagaimana memetakan volume dalam komposisi buruh pelabuhan. Di atas ada jawaban yang menjawab ini. Khusus untuk Windows ini dapat membantu stackoverflow.com/questions/41334021/…
Mohammad Azim
14

Kontainer Docker harus dilihat sebagai 'layanan' mereka sendiri. Untuk memisahkan masalah Anda harus memisahkan fungsi:

1) Data harus dalam wadah data: gunakan volume tertaut untuk mengkloning repo. Wadah data itu kemudian dapat dihubungkan ke layanan yang membutuhkannya.

2) Gunakan sebuah wadah untuk menjalankan tugas kloning git, (yaitu hanya pekerjaan kloning) yang menghubungkan wadah data ke dalamnya ketika Anda menjalankannya.

3) Sama untuk ssh-key: letakkan itu volume (seperti yang disarankan di atas) dan tautkan ke layanan git clone saat Anda membutuhkannya

Dengan begitu, baik tugas kloning dan kuncinya adalah fana dan hanya aktif bila diperlukan.

Sekarang jika aplikasi Anda sendiri adalah antarmuka git, Anda mungkin ingin mempertimbangkan API REST github atau bitbucket secara langsung untuk melakukan pekerjaan Anda: untuk itulah mereka dirancang.

MrE
sumber
13

Baris ini merupakan masalah:

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

Saat menentukan file yang ingin Anda salin ke dalam gambar, Anda hanya dapat menggunakan jalur relatif - relatif terhadap direktori tempat Dockerfile Anda berada. Jadi, Anda sebaiknya menggunakan:

ADD id_rsa /root/.ssh/id_rsa

Dan letakkan file id_rsa ke direktori yang sama dengan Dockerfile Anda.

Lihat ini untuk lebih jelasnya: http://docs.docker.io/reference/builder/#add

Dan Keder
sumber
4
Ini juga masalah keamanan karena menempatkan kunci pribadi ke dalam gambar yang dapat dengan mudah dilupakan.
Mike D
docker cphanya menaruhnya di wadah dan bukan gambar, kan?
Alexander Mills
13

Kami memiliki masalah yang sama ketika melakukan npm install di docker build time.

Terinspirasi dari solusi dari Daniel van Flymen dan menggabungkannya dengan git url menulis ulang , kami menemukan metode yang lebih sederhana untuk mengotentikasi instalasi npm dari repositori github pribadi - kami menggunakan token oauth2 alih-alih kunci.

Dalam kasus kami, dependensi npm ditentukan sebagai "git + https://github.com/ ..."

Untuk otentikasi dalam wadah, url harus ditulis ulang agar sesuai untuk otentikasi ssh (ssh: //[email protected]/) atau otentikasi token (https: // $ {GITHUB_TOKEN} @ github.com /)

Membangun perintah:

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

Sayangnya, saya di buruh pelabuhan 1.9, jadi --squash opsi belum ada, akhirnya perlu ditambahkan

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
Markko Paas
sumber
11

Teruskan soket otentikasi ssh ke wadah:

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

Script Anda akan dapat melakukan a git clone .

Ekstra: Jika Anda ingin file yang dikloning milik pengguna tertentu yang perlu Anda gunakan chownkarena menggunakan pengguna lain selain root di dalam wadah akan membuatgit gagal.

Anda dapat melakukan penerbitan ini ke lingkungan kontainer beberapa variabel tambahan:

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

Setelah Anda mengkloning, Anda harus menjalankan chown $OWNER_USER:$OWNER_GROUP -R <source_folder>untuk mengatur kepemilikan yang tepat sebelum Anda meninggalkan wadah sehingga file dapat diakses oleh pengguna non-root di luar wadah.

edupo
sumber
1
Dalam versi Docker yang lebih baru, Anda dapat meneruskan -u root:$(id -u $USER)setidaknya memiliki file yang dimiliki oleh kelompok utama yang sama dengan pengguna Anda, yang seharusnya membuat semuanya setidaknya dapat dibaca tanpa sudokecuali ada sesuatu yang membuatnya dengan 0600izin.
dragon788
@ dragon788 Saya pikir Anda memiliki kesalahan ketik: -u root:$(id -u $USER)seharusnya -g.
edupo
Panggilan bagus! Saya sepertinya tidak dapat memperbaikinya dari ponsel, akan segera mencoba di desktop.
dragon788
Saya punya /tmp/ssh_auth.sock: No such file or directorysekarang itu /tmp/ssh-vid8Zzi8UILE/agent.46016pada mesin host saya
vladkras
@vladkras kesalahannya cukup umum. Bisa disebabkan karena izin di /tmpdalam wadah Anda. Atau salah ketik pada perintah docker run. Pastikan bahwa pernyataan binding sudah benar -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: Urutan itu penting dan titik koma juga penting. Silakan periksa dokumentasi buruh pelabuhan untuk bantuan lebih lanjut.
edupo
10

Seperti eczajk sudah mengomentari jawaban Daniel van Flymen itu tampaknya tidak aman untuk menghapus kunci dan menggunakan --squash, karena mereka masih akan terlihat dalam sejarah ( docker history --no-trunc).

Sebagai gantinya dengan Docker 18.09, Anda sekarang dapat menggunakan fitur "build secrets". Dalam kasus saya, saya menggandakan repo git pribadi menggunakan kunci SSH host saya dengan yang berikut di Dockerfile saya:

# syntax=docker/dockerfile:experimental

[...]

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

[...]

Untuk dapat menggunakan ini, Anda harus mengaktifkan backend BuildKit baru sebelum menjalankan docker build:

export DOCKER_BUILDKIT=1

Dan Anda perlu menambahkan --ssh defaultparameter kedocker build .

Info lebih lanjut tentang ini di sini: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

frsc
sumber
1
IMHO solusi terbaik. Saya harus melakukan dua hal lagi untuk membuatnya bekerja: 1) tambahkan kunci pribadi saya ke ssh-agent dengan ssh-add ~/.ssh/id_rsadan 2) tambahkan host git ke known_hosts, yaitu untuk bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Moritz Ringler
Saya belum bisa membuatnya bekerja sama sekali. Saya masih mendapatkan kesalahan izin: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.Ini meskipun melewati --ssh defaultflag di build docker saya, dan menggunakan --mount=type=sshdalam menjalankan perintah di mana saya git clone. Saya dapat mengkloning repo yang sama tidak ada masalah pada mesin build. Itu hanya gagal di buruh pelabuhan membangun kontainer. Saya menduga bahwa versi mac Docker sebenarnya tidak melewati klien ssh.
PMende
@ PMende apakah Anda bisa mengetahui masalah ini yang Anda sebutkan karena saya juga menghadapi hal yang sama.
Sadan A.
@SadanArshad Ternyata fungsi ini hanya didukung jika Anda menjalankan Docker dari mesin Linux. Ini tidak berfungsi jika Anda menjalankan perintah Docker dari Mac (dan mungkin Windows, juga, meskipun saya tidak dapat mengonfirmasi).
PMende
Sayang sekali itu tidak bekerja dengan menulis- galangan
Alexis Wilke
9

Masalah ini benar-benar menyebalkan. Karena Anda tidak dapat menambahkan / menyalin file apa pun di luar konteks dockerfile, yang berarti tidak mungkin untuk hanya menautkan ~ / .ssh / id_rsa ke /root/.ssh/id_rsa gambar, dan ketika Anda benar-benar memerlukan kunci untuk melakukan beberapa hal sshed seperti git klon dari tautan repo pribadi ..., selama pembuatan gambar buruh pelabuhan Anda.

Bagaimanapun, saya menemukan solusi untuk menyelesaikannya, tidak begitu membujuk tetapi berhasil bagi saya.

  1. di dockerfile Anda:

    • tambahkan file ini sebagai /root/.ssh/id_rsa
    • lakukan apa yang Anda inginkan, seperti git clone, komposer ...
    • rm /root/.ssh/id_rsa di akhir
  2. skrip yang harus dilakukan dalam satu pemotretan:

    • cp kunci Anda ke folder holding dockerfile
    • membangun buruh pelabuhan
    • rm kunci yang disalin
  3. kapan saja Anda harus menjalankan sebuah wadah dari gambar ini dengan beberapa persyaratan ssh, cukup tambahkan -v untuk perintah jalankan, seperti:

    run docker -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa - nama perintah wadah image

Solusi ini tidak menghasilkan kunci pribadi di sumber proyek Anda dan gambar buruh pelabuhan yang dibangun, jadi tidak ada masalah keamanan yang perlu dikhawatirkan lagi.

Imeo
sumber
1
"Karena Anda tidak dapat menambahkan / menyalin file apa pun di luar konteks dockerfile," Sudahkah Anda melihat docker cp? Ini digunakan untuk "Menyalin file / folder antara wadah dan host Anda."
Jonathon Reinhart
@ JonathonReinhart, terima kasih sudah menunjukkannya. Ya, docker cpbisa melakukan triknya. Namun dalam situasi ini, saya memerlukan ssh_key selama gambar sedang dibangun, dan tidak ada wadah pada saat itu ... akan memperbarui ekspresi saya yang tidak jelas, terima kasih.
ImLeo
9

Saya mengalami masalah yang sama hari ini dan sedikit memodifikasi versi dengan posting sebelumnya saya menemukan pendekatan ini lebih bermanfaat bagi saya

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

(Perhatikan bahwa hanya baca flag sehingga kontainer tidak akan mengacaukan kunci ssh saya.)

Di dalam wadah sekarang saya dapat menjalankan:

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

Jadi saya tidak mendapatkan Bad owner or permissions on /root/.ssh/..kesalahan yang dicatat oleh @kross

tojo
sumber
Terima kasih! Ini adalah kunci untuk mendapatkannya bekerja untuk saya: memiliki ssh-agent dan ssh-add di satu perintah seperti: ssh-agent bash -c "ssh-add...". Saya kemudian bisa meneruskannya ke docker. Semua contoh sebelumnya yang saya temukan digunakan eval ssh-agent, diikuti oleh ssh-add dan saya tidak dapat menemukan cara untuk melewatkannya evalmelalui perintah run docker.
ryanman
6

Anda juga dapat menautkan direktori .ssh Anda antara tuan rumah dan wadah, saya tidak tahu apakah metode ini memiliki implikasi keamanan tetapi mungkin metode yang paling mudah. Sesuatu seperti ini seharusnya bekerja:

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

Ingatlah bahwa buruh pelabuhan menjalankan dengan sudo (kecuali jika Anda tidak), jika ini adalah kasus Anda akan menggunakan kunci ssh root.

Luis Elizondo
sumber
Menggunakan metode ini berfungsi dengan buruh pelabuhan 0.11 tetapi jika Anda menggunakan ara, itu akan menimbulkan kesalahan panik. Saya tidak tahu mengapa
Luis Elizondo
3
Ini akan menjadi metode yang disukai, triknya adalah menggunakan kunci pengguna host yang tidak terjangkau sebagai root dari penampung. Seperti yang Anda sebutkan, mencoba melakukannya bukan karena pengguna root host menghasilkan Bad owner or permissions on /root/.ssh/config.
Kross
ini hanya dapat digunakan selama docker run, tetapi tidak selama docker build.
ccpizza
3
@ccpizza, saya melihatnya sebagai keuntungan. Banyak dari jawaban ini membiarkan kunci pribadi disimpan dalam gambar; kunci tetap disimpan bahkan setelah Anda menghapus kunci dalam perintah lapisan berikutnya. Dengan memperkenalkan kunci privat hanya selama menjalankan (bukan membangun), mereka hanya bisa ada dalam wadah (bukan gambar).
cowlinator
6

Mulai dari docker API 1.39+(Periksa versi API dengan docker version) docker build memungkinkan --sshopsi dengan soket agen atau kunci untuk memungkinkan Docker Engine meneruskan koneksi agen SSH.

Bangun Komando

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

Info lebih lanjut:

Edison Arango
sumber
1
Perluasan tilde tidak berhasil untuk saya; Saya punya: could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Gunakan jalur lengkap jika itu tidak berhasil.
slhck
3

Jika Anda tidak peduli dengan keamanan kunci SSH Anda, ada banyak jawaban bagus di sini. Jika ya, jawaban terbaik yang saya temukan adalah dari tautan di komentar di atas ke komentar GitHub ini oleh diegocsandrim . Sehingga orang lain lebih mungkin melihatnya, dan kalau-kalau repo itu hilang, berikut adalah versi yang diedit dari jawaban itu:

Sebagian besar solusi di sini akhirnya meninggalkan kunci pribadi dalam gambar. Ini buruk, karena siapa pun yang memiliki akses ke gambar memiliki akses ke kunci pribadi Anda. Karena kita tidak cukup tahu tentang perilakusquash , ini mungkin masih menjadi masalah bahkan jika Anda menghapus kunci dan menekan lapisan itu.

Kami membuat URL pre-sign untuk mengakses kunci dengan aws s3 cli, dan membatasi akses selama sekitar 5 menit, kami menyimpan URL pre-sign ini ke dalam file di direktori repo, kemudian di dockerfile kami menambahkannya ke gambar.

Di dockerfile kami memiliki perintah RUN yang melakukan semua langkah ini: gunakan URL pra-sing untuk mendapatkan kunci ssh, jalankan npm install, dan hapus kunci ssh.

Dengan melakukan ini dalam satu perintah tunggal kunci ssh tidak akan disimpan dalam lapisan apa pun, tetapi URL pra-tandatangan akan disimpan, dan ini bukan masalah karena URL tidak akan valid setelah 5 menit.

Skrip build terlihat seperti:

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

Dockerfile terlihat seperti ini:

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 [email protected] || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]
Sam H.
sumber
1
Masalah dengan solusi ini adalah karena pre_sign_url akan berubah setiap waktu, instalasi npm tidak dapat di-cache bahkan tidak ada perubahan pada file paket.json. Lebih baik untuk mendapatkan kunci dalam build.sh dan mengaturnya sebagai argumen build sehingga tidak akan berubah setiap saat
York Yang
3

Tinjauan singkat tentang tantangan SSH di dalam wadah Docker dirinci di sini . Untuk menghubungkan ke remote yang terpercaya dari dalam sebuah wadah tanpa membocorkan rahasia ada beberapa cara:

Selain itu ada juga kemungkinan menggunakan key-store yang berjalan di wadah buruh pelabuhan terpisah yang dapat diakses saat runtime saat menggunakan Compose. Kelemahan di sini adalah kompleksitas tambahan karena mesin yang diperlukan untuk membuat dan mengelola keystore seperti Vault oleh HashiCorp .

Untuk penggunaan kunci SSH dalam wadah Docker yang berdiri sendiri lihat metode yang ditautkan di atas dan pertimbangkan kelemahan masing-masing tergantung pada kebutuhan spesifik Anda. Namun, jika Anda menjalankan di dalam Compose dan ingin membagikan kunci ke aplikasi saat runtime (mencerminkan praktik OP) coba ini:

  • Buat docker-compose.envfile dan tambahkan ke file Anda.gitignore file .
  • Perbarui docker-compose.ymldan tambahkanenv_file layanan yang memerlukan kunci.
  • Akses kunci publik dari lingkungan saat runtime aplikasi, misalnya process.node.DEPLOYER_RSA_PUBKEYdalam kasus aplikasi Node.js.

Pendekatan di atas ideal untuk pengembangan dan pengujian dan, meskipun bisa memenuhi persyaratan produksi, dalam produksi Anda lebih baik menggunakan salah satu metode lain yang diidentifikasi di atas.

Sumber daya tambahan:

Josh Habdas
sumber
3

Anda dapat menggunakan multi stage build untuk membangun kontainer Ini adalah pendekatan yang dapat Anda ambil: -

Tahap 1 membangun gambar dengan 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

Tahap 2: bangun wadah Anda

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"] 

tambahkan atribut env di file penulisan Anda:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

lalu berikan args dari skrip build seperti ini:

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

Dan lepaskan wadah perantara untuk keamanan. Ini akan membantu Anda bersorak.

Devesh
sumber
2

Cara sederhana dan aman untuk mencapai ini tanpa menyimpan kunci Anda di lapisan gambar Docker, atau melalui senam ssh_agent adalah:

  1. Sebagai salah satu langkah di Anda Dockerfile, buat .sshdirektori dengan menambahkan:

    RUN mkdir -p /root/.ssh

  2. Di bawah ini menunjukkan bahwa Anda ingin memasang direktori ssh sebagai volume:

    VOLUME [ "/root/.ssh" ]

  3. Pastikan bahwa wadah Anda ssh_configtahu di mana menemukan kunci publik dengan menambahkan baris ini:

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

  4. Paparkan .sshdirektori pengguna lokal Anda ke wadah saat runtime:

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

    Atau di dockerCompose.ymladd Anda ini di bawah tombol volume layanan:

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

Final Anda Dockerfileharus berisi sesuatu seperti:

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" ]
Buchanora
sumber
1

Saya mencoba mengatasi masalahnya dengan cara lain: menambahkan kunci ssh publik ke gambar. Tetapi dalam percobaan saya, saya menemukan bahwa "buruh pelabuhan cp" adalah untuk menyalin DARI wadah ke host. Butir 3 dalam jawaban dengan berderit sepertinya mengatakan Anda dapat menggunakan buruh pelabuhan untuk menyuntikkan file ke dalam wadah. Lihat https://docs.docker.com/engine/reference/commandline/cp/

kutipan

Salin file / folder dari sistem file wadah ke jalur host. Path relatif terhadap root sistem file.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH
EricGreg
sumber
URL ini tampaknya rusak sekarang.
slm
Ini sudah usang atau salah. Ia dapat menyalin salah satu arah, paling lambat 1.8.2.
Jonathon Reinhart
1

Anda bisa memasukkan kunci yang diotorisasi ke wadah Anda menggunakan folder bersama dan mengatur izin menggunakan file buruh pelabuhan seperti ini:

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

Dan menjalankan docker Anda berisi sesuatu seperti berikut ini untuk berbagi direktori auth pada host (memegang authorised_keys) dengan wadah kemudian buka port ssh yang akan dapat diakses melalui port 7001 pada host.

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

Anda mungkin ingin melihat https://github.com/jpetazzo/nsenter yang tampaknya merupakan cara lain untuk membuka shell pada wadah dan menjalankan perintah dalam wadah.

andrew pate
sumber
1

Terlambat untuk pesta, bagaimana dengan ini yang akan membuat kunci sistem operasi host Anda tersedia untuk root di dalam wadah, dengan cepat:

docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh [email protected]"

Saya tidak mendukung penggunaan Dockerfile untuk menginstal kunci karena iterasi wadah Anda dapat meninggalkan kunci pribadi.

Jepper
sumber
0

Anda dapat menggunakan rahasia untuk mengelola data sensitif apa pun yang dibutuhkan wadah saat runtime tetapi Anda tidak ingin menyimpannya di dalam gambar atau dalam kontrol sumber, seperti:

  • Nama pengguna dan kata sandi
  • Sertifikat dan kunci TLS
  • Kunci SSH
  • Data penting lainnya seperti nama database atau server internal
  • String umum atau konten biner (berukuran hingga 500 kb)

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

Saya mencoba mencari cara menambahkan kunci masuk ke wadah untuk digunakan selama runtime (bukan membangun) dan menemukan pertanyaan ini. Rahasia Docker tampaknya menjadi solusi untuk kasus penggunaan saya, dan karena tidak ada yang menyebutkannya, saya akan menambahkannya.

Travis Britz
sumber
0

Dalam kasus saya, saya punya masalah dengan nodejs dan 'npm i' dari repositori jarak jauh. Saya memperbaikinya menambahkan pengguna 'simpul' ke wadah nodejs dan 700 ke ~ / .ssh dalam wadah.

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

setelah itu mulai bekerja

Дмитрий Урбанович
sumber
-1

Cara paling sederhana, dapatkan akun launchpad dan gunakan: ssh-import-id

Sam Saffron
sumber
8
Pertanyaannya adalah tentang kunci pribadi. ssh-import-idSepertinya itu hanya mengimpor kunci publik.
cddr
-1

Dalam wadah buruh pelabuhan yang sedang berjalan, Anda dapat mengeluarkan ssh-keygen dengan opsi buruh pelabuhan -i (interaktif). Ini akan meneruskan wadah meminta untuk membuat kunci di dalam wadah buruh pelabuhan.

Jerome Anthony
sumber
1
Lalu apa? Anda tidak dapat melakukan apa pun setelah ini, karena Anda tidak memiliki izin untuk melakukannya.
Jonathon Reinhart
-1

Untuk debian / root / berwenang_kunci:

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
StanislavKo
sumber