Docker konteynerinin içindeki SSH anahtarlarını kullanma


324

Git (git clone & git push çalıştırmak gibi) ile çeşitli eğlenceli şeyler yürüten bir uygulama var ve ben docker-boyutlandırmak için çalışıyorum.

Kapsayıcı 'kullanıcı' kullanmak için kapsayıcıya bir SSH anahtarı eklemek gerekir gerçi bir sorunla karşılaşıyorum.

Bir kopya ssh sarıcı oluşturma /root/.ssh/, değiştirme, değiştirme $HOME, ve hala şans denedim .

İşte referans için Dockerfile:

#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 git komutlarını çalıştırır git pull


3
Bu soruya yaklaşan herkes, bir güvenlik deliği oluşturmak ve dikkatli değilseniz burada unutmak kolay olduğu için oyunun sonunda düşünmelidir. Tüm cevapları okuyun ve akıllıca seçin.
Josh Habdas

Yanıtlar:


144

Derleme zamanında SSH kullanmanız daha zor bir sorundur. Örneğin, kullanıyorsanız git cloneveya benim durumumda pipve npmözel bir depodan indirmek için.

Bulduğum çözüm anahtarlarınızı --build-argbayrağını kullanarak eklemektir . Daha sonra --squashkatmanları birleştirmek için yeni deneysel komutu (1.13 eklendi) kullanabilirsiniz, böylece anahtarlar kaldırıldıktan sonra artık kullanılabilir olmaz. İşte benim çözümüm:

Derleme komutu

$ 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

Güncelleme: Docker 1.13 kullanıyorsanız ve üzerinde deneysel özellikler varsa --squash, katmanları birleştirecek, SSH anahtarlarını kaldıracak ve gizlenecek build komutuna ekleyebilirsiniz docker history.


13
Bu GitHub sorunu iş parçacığı , bu yaklaşımın hala güvenli olmadığını gösterir. Benzer bir çözüm için bu yoruma bakın .
eczajk

4
Ezmek yerine başka bir çözüm, anahtarı aynı RUN komutuna eklemek ve kaldırmak ve ekleme ve çıkarma arasında ihtiyacınız olan şey için kullanmanızdır.
Benjamin Hammer Nørgaard

2
id_rsa.pubDosyayı oluşturmak için gerekli olmayan satırları kaldırabilirsiniz .
LCB


Anahtarınız parola korumalıysa, $(openssl rsa -in ~/.ssh/id_rsa)bunun yerine kullanın
saatinde BroiSatse

89

Ubuntu kullanırken çıkıyor, ssh_config doğru değil. Eklemelisin

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

ssh anahtarınızı tanımasını sağlamak için Dockerfile'ınıza gönderin.


2
Muhtemelen böyle doğru kullanıcı adını da ayarlamanız gerekirRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone

1
Neden birisi özel anahtarı bir ana bilgisayardan bir kapsayıcıya kopyalasın? Komut tamam, ama yukarıda belirtilenleri yapmanın anlamını görmüyorum ...
Vladimir Djuricic

12
Bu güvenli değil! Docker'ın en son 1.13 sürümü için aşağıdaki çözümüme bakın. @ebensing
Daniel van Flymen

1
@VladimirDjuricic Ancak dağıtım anahtarları gibi şeyler var.
Zelphir Kaltstahl

aslında ubuntu minimal kapsayıcı ssh düzgün kurmak için ssh-keygen -A çalıştırmak gerekir. Ardından pub / priv anahtarları ekleyebilir ve sshd'yi başlatabilirsiniz. Dockerfile benim bu giriş var: 'RUN ssh-keygen -A' adımlardan biri olarak.
piotrektt

84

Not : Bu yaklaşımı yalnızca özel ve her zaman olacak görüntüler için kullanın !

Katman komutundaki anahtarı ekledikten sonra kaldırsanız bile, ssh tuşu görüntü içinde kayıtlı kalır ( bu yazıdaki yorumlara bakın ).

Benim durumumda bu tamam, bu yüzden ne kullanıyorum:

# 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
Bu, anahtarınızı görüntüde tutacaktır, yapma.
CppLearner

12
@CppLearner haklısınız, bu anahtar görüntüyü saklar ve bu bazı durumlarda bir güvenlik sorunu olabilir. Bunu vurguladığınız için teşekkürler. Ancak, bunun mükemmel bir şekilde kaydedildiği birçok durum vardır. Örneğin, özel bir depoda saklanan görüntüler veya doğrudan yerel anahtarları görüntüye kopyalayan bir üretim sunucusunda oluşturulan görüntüler için.
yellowcap

2
Ayrıca, satıcılarınızı Dockerfile içine yüklerseniz, satıcılar yüklendikten sonra ssh anahtarını kaldırmanızı engelleyen hiçbir şey yoktur.
SebScoFr

2
@SebScoFr, görünüşe göre tuşları daha sonraki bir komutta kaldırsanız bile katmanlardan birinde saklanacaktır (güncellenmiş cevaptaki bağlantıya bakınız). Böylece görüntü her zaman ssh tuşunu açığa çıkarır ve çözüm yalnızca özel görüntüler için kullanılmalıdır!
yellowcap

1
@yellowcap yapmazsan
inşaa

56

Docker compose kullanıyorsanız kolay bir seçim SSH ajanını böyle iletmektir:

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

23
Unix etki alanı soketlerine proxy uygulanmadığından docker-machine (VirtualBox aracılığıyla) veya Mac için Docker (xhyve kullanan) kullanıyor olsun, Mac ana bilgisayarları için işe yaramadığını unutmayın.
Joe Shaw

SSH_AUTH_SOCKssh-agent yolunu içeren bir değişkendir
Aistis


1
ssh-forwarding artık macOS ana bilgisayarlarında da desteklenmektedir - yolunu monte etmek yerine, $SSH_AUTH_SOCKbu yolu bağlamanız gerekir - /run/host-services/ssh-auth.sock.
Jakub

47

Genişleyen Peter Grainger cevabı kullandığım başardı çok aşamalı yapı Docker 17.05 beri mevcut. Resmi sayfa devletleri:

Çok aşamalı derlemelerle, FROMDockerfile dosyanızda birden çok ifade kullanırsınız. Her FROMtalimat farklı bir taban kullanabilir ve her biri yapının yeni bir aşamasını başlatır. Son görüntüde istemediğiniz her şeyi geride bırakarak yapay nesneleri bir aşamadan diğerine seçici olarak kopyalayabilirsiniz.

Bunu akılda tutmak, Dockerfileüç yapım aşaması ekleme örneğidir . İstemci web uygulamasının üretim görüntüsünü oluşturmak içindir.

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

.dockerignore.gitignoredosyanın içeriğini tekrarlar ( projenin node_modulessonuç distdizinlerinin kopyalanmasını engeller ve engeller ):

.idea
dist
node_modules
*.log

Bir görüntü oluşturmak için komut örneği:

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

Özel SSH anahtarınızın bir parolası yoksa, yalnızca boş SSH_KEY_PASSPHRASEargüman belirtin .

Bu nasıl çalışır:

1). Yalnızca ilk aşamada package.json, yarn.lockdosyalar ve özel SSH anahtarı adlı ilk ara görüntüye kopyalanır sources. Daha fazla SSH anahtarı parolası isteminden kaçınmak için otomatik olarak eklenir ssh-agent. Son olarak yarnkomut, NPM'den gerekli tüm bağımlılıkları yükler ve Bitbucket'ten SSH üzerinden özel git depolarını klonlar.

2). İkinci aşama, web uygulamasının kaynak kodunu oluşturur ve küçültür ve distadı verilen bir sonraki ara görüntünün dizinine yerleştirir production. Yüklü kaynak kodunun, bu satır tarafından ilk aşamada üretilen node_modulesadlı resimden kopyalandığını unutmayın sources:

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

Muhtemelen şu satır da olabilir:

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

Burada sadece node_modulesilk ara resimdeki dizinimiz var, artık SSH_KEYve SSH_KEY_PASSPHRASEargümanlar yok. Derleme için gereken geri kalanlar proje dizinimizden kopyalanır.

3). Üçüncü aşamada, ezze/geoport:0.6.0yalnızca distikinci ara görüntüdeki dizini ekleyerek productionve bir web sunucusu başlatmak için Node Express'i yükleyerek etiketlenecek son görüntünün boyutunu küçültüriz .

Resimleri listelemek şöyle bir çıktı verir:

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

burada etiketlenmemiş görüntüler birinci ve ikinci ara yapım aşamalarına karşılık gelir.

Eğer koşarsan

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

Eğer herhangi bir şekilde bahsedilen görmez SSH_KEYve SSH_KEY_PASSPHRASEson görüntüde.


Eski yazı, ama vurgulamak istiyorum, bu 18.09 öncesi bunu yapmanın en iyi yoludur. Squash gereksizdir ve riske eğilimlidir. Çok aşamalı olarak, sadece istediğiniz eserleri getirdiğinizi biliyorsunuz. Squash'ı istemediğiniz dosyaları devre dışı bırakma olarak düşünün ve çok aşamalı olarak katılma olarak düşünün. Bu cevabın daha yüksek olması gerekiyor. Görüntüde ssh tuşlarını pişirmek korkunç bir uygulamadır.
mritalian

@ezze Bu çok yararlı yazı için çok teşekkür ederim :) SSH-ajanı beni çılgına çeviriyor, u yaptığınız gibi bir şey yaptım: Docker yapı günlüklerinde doğru bir şekilde görüyorum Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)ama başka bir RUN'da veya hatta RUN'da kontrol ettiğimde komutunu ssh-add -lvererek bana "Temsilcinin kimliği yok" der. Tüylerimi çıkarmaya başladın mı?
Alex

40

Ssh anahtarını enjekte etmek için bir kap içine birden fazla çözümünüz var:

  1. Talimatla birlikte bir Dockerfile kullanarak ADDoluşturma işleminiz sırasında enjekte edebilirsiniz

  2. Sadece şöyle bir şey yapmak cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. docker cpBir kap çalışırken dosyaları enjekte etmenizi sağlayan komutu kullanma .


2
Yani, şu andan itibaren, /root/.ssh/id_rsa içine kopyalamayı denedim ama yine de "Ana bilgisayar anahtarı doğrulaması başarısız oldu. Ölümcül: Uzak uç beklenmedik bir şekilde kapatıldı" hatalarını alıyorum. anahtarı herhangi bir nedenle kullanmıyor. Yani sisteme ssh anahtarı olarak kullanmasını söylemek için yapmam gereken başka bir şey olduğunu düşünüyorum. Tam olarak nasıl hata ayıklanacağından emin değilim. (ve bu anahtarın ana bilgisayardan sorunsuz çalıştığı için çalıştığını biliyorum)
Ağustos'ta

/ etc / ssh / ssh_config dosyasının doğru anahtar dosyasını hedeflediğinden emin olabilir misiniz?
creack

1
Liman işçisi konteynerinin dosyalarını incelemek için iyi bir yol var mı? Yoksa sadece geçerli bir yapılandırmada kopyalamayı denemeli miyim?
13'te

3
Sadece 'base' imajını denedim, apt-get install openssh-serveranahtarımı /root/.ssh/id_rsa 'a koyup koydum ve iyi çalıştı. Hangi resmi kullanıyorsunuz?
13'te

bir kabın dosyasını incelemeniz gerekiyorsa, en iyi yol sonuçlanan görüntüyü 'cat' ile çalıştırmak ve çalıştırmaktır.
creack

15

Platformlar arası bir çözüm, ana bilgisayarın klasörünü kapla paylaşmak için bir bağlama bağlaması kullanmaktır .ssh:

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

Bu yaklaşımı yönlendiren ajana benzer şekilde, ortak anahtarlar kapsayıcı için erişilebilir olacaktır. Diğer bir olumsuz yanı, kök olmayan bir kullanıcıyla da çalışması ve GitHub'a bağlanmanızı sağlamasıdır. Bununla birlikte, dikkate alınması gereken bir uyarı, .sshklasördeki tüm içeriğin (özel anahtarlar dahil) paylaşılacağıdır, bu nedenle bu yaklaşım yalnızca geliştirme ve yalnızca güvenilir kap resimleri için istenir.


1
bu işe yarayabilir, ama docker buildsadece sırasında değildocker run
Alexander Mills

3
Mesele bu. Ssh anahtarlarınızı bir docker dosyasının içine koymak istemezsiniz.
Mohammad Azim

2
SSH aracı iletimi Linux dışında çalışmazsa, bu, çok fazla karışıklık olmadan bir geliştirme ortamında çalışmaya başlamak için iyi bir çözümdür.
Josh Habdas

docker-compose upYerel Windows 10'umda docker çalıştırıyorum . Bu senaryoda çözümünüzü nasıl kullanmalıyım?
llaaalu

Temel olarak docker compose'deki hacminin nasıl haritalanacağını soruyorsunuz. Yukarıda buna cevap veren bir cevap var. Özellikle Windows için bu stackoverflow.com/questions/41334021/…
Mohammad Azim

14

Liman işçisi konteynırları kendi hizmetleri olarak görülmelidir. Endişeleri ayırmak için işlevleri ayırmalısınız:

1) Veriler bir veri konteynerinde olmalıdır: repoyu klonlamak için bağlantılı bir birim kullanın. Bu veri taşıyıcısı daha sonra ihtiyacı olan hizmete bağlanabilir.

2) Git klonlama görevini çalıştırmak için bir kap kullanın (yani, yalnızca iş klonlamaktır), çalıştırdığınızda veri kabını ona bağlar.

3) ssh-key için aynı: bir hacim (yukarıda önerildiği gibi) koyun ve ihtiyacınız olduğunda git klon hizmetine bağlayın

Bu şekilde, hem klonlama görevi hem de anahtar geçici ve yalnızca gerektiğinde etkindir.

Şimdi uygulamanızın kendisi bir git arayüzü ise, işinizi yapmak için doğrudan github veya bitbucket REST API'lerini düşünebilirsiniz: bunun için tasarlandılar.


13

Bu satır bir sorun:

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

Görüntüye kopyalamak istediğiniz dosyaları belirtirken, Dockerfile dosyanızın bulunduğu dizine göre yalnızca göreli yolları kullanabilirsiniz. Bunun yerine şunu kullanmalısınız:

ADD id_rsa /root/.ssh/id_rsa

Ve id_rsa dosyasını Dockerfile dosyanızın bulunduğu dizine koyun.

Daha fazla ayrıntı için buna göz atın: http://docs.docker.io/reference/builder/#add


4
Bu aynı zamanda güvenlik sorunudur, çünkü kolayca unutulabilecek bir görüntüye özel bir anahtar koyar.
Mike D

docker cpsadece kabın içine koyar, görüntüye değil, değil mi?
Alexander Mills

13

Docker oluşturma süresinde npm yüklemesi yaparken benzer bir sorun yaşadık.

Daniel van Flymen'in çözümünden esinlenerek ve git url yeniden yazma ile birleştirerek , özel github depolarından npm yüklemesini doğrulamak için biraz daha basit bir yöntem bulduk - anahtarlar yerine oauth2 belirteçleri kullandık.

Bizim durumumuzda, npm bağımlılıkları "git + https://github.com/ ..." olarak belirtildi.

Kapsayıcıdaki kimlik doğrulaması için URL'lerin ssh kimlik doğrulaması (ssh: //git@github.com/) veya belirteç kimlik doğrulaması (https: // $ {GITHUB_TOKEN} @ github.com /) için uygun olacak şekilde yeniden yazılması gerekir.

Derleme komutu:

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

Ne yazık ki, docker 1.9 kullanıyorum, bu yüzden --squash seçeneği henüz yok, sonunda eklenmesi gerekiyor

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

Ssh kimlik doğrulama soketini kaba iletin:

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

Betiğiniz bir git clone.

Ekstra: Klonlanan dosyaların belirli bir kullanıcıya ait olmasını istiyorsanız chown, kapsayıcı içindeki kökten başka bir kullanıcı kullanmanız gitbaşarısız olacağından kullanmanız gerekir .

Bu yayınlamayı kabın ortamına bazı ek değişkenler yapabilirsiniz:

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

Klonladıktan sonra chown $OWNER_USER:$OWNER_GROUP -R <source_folder>, konteynırdan ayrılmadan önce dosyalara kök dışındaki bir kullanıcı tarafından erişilebilmesi için uygun sahipliği ayarlamanız gerekir .


1
Yeni Docker versiyonlarında geçebilir -u root:$(id -u $USER)en azından okunabilir olmadan en azından hepsini yapmalıdır sizin kullanıcı olarak aynı birincil grup tarafından sahip olunan dosyaları var sudobir şey ile onları yaratıyor sürece 0600izinleri.
dragon788

@ dragon788 Bence bir yazım hatası var: -u root:$(id -u $USER)olmalı -g.
edupo

İyi karar! Mobil cihazdan düzeltemiyorum, yakında masaüstünde deneyeceğim.
dragon788

Ben /tmp/ssh_auth.sock: No such file or directoryöyle şimdi /tmp/ssh-vid8Zzi8UILE/agent.46016benim ana makinede
vladkras

@vladkras hata oldukça genel. /tmpKapsayıcınızdaki izinlerden kaynaklanabilir . Veya docker run komutunda bir yazım hatası. Bind ifadesinin doğru olduğundan emin olun -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: Sıralama önemlidir ve noktalı virgül de önemlidir. Daha fazla yardım için docker belgelerine bakın.
edupo

10

Eczajk Daniel van Flymen'in cevabında zaten yorumladığı gibi, anahtarları kaldırmak ve kullanmak güvenli görünmüyor --squash, çünkü tarihte hala görünecekler ( docker history --no-trunc).

Bunun yerine Docker 18.09 ile artık "sır oluşturma" özelliğini kullanabilirsiniz. Benim durumumda, ana bilgisayar SSH anahtarımı kullanarak Dockerfile dosyamda özel bir git repo kopyaladım:

# syntax=docker/dockerfile:experimental

[...]

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

[...]

Bunu kullanabilmek için çalıştırmadan önce yeni BuildKit arka ucunu etkinleştirmeniz gerekir docker build:

export DOCKER_BUILDKIT=1

Ve --ssh defaultparametresini şuraya eklemeniz gerekir docker build.

Bununla ilgili daha fazla bilgi için: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
En iyi çözüm IMHO. Çalışması için iki şey daha yapmak zorunda kaldım: 1) ssh-agent'a özel anahtarımı ssh-add ~/.ssh/id_rsaekleyin ve 2) bitbucket için bilinen ana makinelere git ana bilgisayarını ekleyin:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Moritz Ringler

Bunu hiç çalıştıramadım. Hala izin hataları alıyorum: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.Bu --ssh defaultbenim docker yapısında bayrak geçen ve --mount=type=sshben burada run komutunu kullanarak rağmen git clone. Ben aynı repo klonlama yapamıyorum sorun makinede. Basitçe docker yapı kapsayıcısında başarısız olur. Docker'ın mac sürümünün aslında ssh istemcisini geçmediğinden şüpheleniyorum.
PMende

@PMende, bahsettiğiniz bu sorunu anlayabildiniz, çünkü aynı şeyle karşı karşıyayım.
Sadan

@SadanArshad Bu işlevsellik şu anda yalnızca Docker'ı bir Linux makinesinden çalıştırıyorsanız destekleniyor. Docker komutlarınızı bir Mac'ten (ve muhtemelen Windows da çalıştırıyorsanız) işe yaramazsa da çalışmaz.
PMende


9

Bu sorun gerçekten can sıkıcı bir konudur. Dockerfile bağlamının dışında herhangi bir dosya ekleyemeyeceğiniz / kopyalayamayacağınız için, bu, ~ / .ssh / id_rsa'yı görüntünün /root/.ssh/id_rsa'sına bağlamanız imkansız olduğu anlamına gelir ve bazı sshed şeyleri yapmak için kesinlikle bir anahtara ihtiyacınız olduğunda docker görüntünüzün oluşturulması sırasında özel bir repo bağlantısından git klonu gibi ....

Her neyse, geçici çözüm için bir çözüm buldum, çok ikna edici değilim ama benim için çalıştım.

  1. dockerfile dosyasında:

    • bu dosyayı /root/.ssh/id_rsa olarak ekle
    • git klon, besteci gibi istediğinizi yapın ...
    • sonunda rm /root/.ssh/id_rsa
  2. tek çekimde yapılacak bir senaryo:

    • cp anahtarınızı dockerfile tutan klasöre
    • liman işçisi inşası
    • kopyalanan anahtarı rm
  3. bazı ssh gereksinimleriyle bu görüntüden bir kapsayıcı çalıştırmanız gerektiğinde, sadece aşağıdaki gibi run komutu için -v ekleyin:

    docker run -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa - ad kapsayıcısı görüntü komutu

Bu çözüm, hem proje kaynağınızda hem de yerleşik docker görüntüsünde özel bir anahtarla sonuçlanmadığından, artık endişelenecek bir güvenlik sorunu yoktur.


1
"Dockerfile bağlamının dışında herhangi bir dosya ekleyemediğiniz / kopyalayamadığınız için," Gördünüzdocker cp? "Bir kapsayıcı ve sunucunuz arasında dosya / klasör kopyalamak için kullanılır."
Jonathon Reinhart

@JonathonReinhart, bunu belirttiğin için teşekkürler. Evet, docker cphile yapabilir. Ancak bu durumda, inşa edilen görüntü sırasında ssh_key'e ihtiyacım vardı ve o zaman kap yok ... belirsiz ifademi güncelleyecek, yine de teşekkürler.
ImLeo

9

Bugün aynı problemle karşılaştım ve önceki yayınlarla biraz değiştirilmiş versiyon Bu yaklaşımı benim için daha yararlı buldum

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

(Kapsayıcı herhangi bir durumda ssh anahtarımı karıştırmayacak şekilde salt okunur olarak işaretlendiğini unutmayın.)

Konteyner içinde şimdi çalıştırabilirim:

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

Bu yüzden Bad owner or permissions on /root/.ssh/..@kross tarafından belirtilen hatayı almıyorum


Teşekkür ederim! Gibi tek bir komut ssh-agent ve ssh-add sahip: Bu tuş benim için çalışan bulmaktı: ssh-agent bash -c "ssh-add...". Sonra bunu docker koşusuna aktarabilirim. Daha önce bulduğum tüm örnekleri eval ssh-agentssh-add kullandım ve bunu evaldocker run komutundan geçirmenin bir yolunu bulamadım .
ryanman


6

Ayrıca .ssh dizinini ana bilgisayar ve kapsayıcı arasında bağlayabilirsiniz, bu yöntemin herhangi bir güvenlik etkisi olup olmadığını bilmiyorum ama en kolay yöntem olabilir. Böyle bir şey işe yaramalı:

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

Docker'ın sudo ile çalıştığını (yapmadığınız sürece) unutmayın, bu durumda root ssh anahtarlarını kullanacaksınız.


Bu yöntemi kullanmak docker 0.11 ile çalışır, ancak incir kullanırsanız panik hatası verir. Neden bilmiyorum
Luis Elizondo

3
Bu tercih edilen bir yöntem olurdu, püf noktası ayrıcalıksız ana bilgisayar kullanıcı anahtarlarımı kabın kökü olarak kullanmak olacaktır. Bahsettiğiniz gibi, ana bilgisayar root kullanıcısı olarak bunu yapmaya çalışmayın Bad owner or permissions on /root/.ssh/config.
kross

bu sadece sırasında kullanılabilir docker run, ancak sırasında kullanılamaz docker build.
ccpizza

3
@ccpizza, bunu bir avantaj olarak görüyorum. Bu yanıtların çoğu, özel anahtarları bir görüntüde saklar; sonraki katman komutunda anahtarı çıkardıktan sonra bile anahtar kayıtlı kalır. Özel anahtarları yalnızca çalıştırma sırasında (derleme değil) tanıtarak, yalnızca kapta (görüntüde değil) var olabilirler.
cowlinator

6

Başlayarak docker API 1.39+(olan Çek API sürümü docker versionliman işçisi yapı) verir --sshileri SSH ajanı bağlantılarına Docker Engine izin bir ajan soketi veya anahtarları biriyle seçeneği.

Yapı Komutu

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

Daha fazla bilgi:


1
Tilde genişleme benim için çalışmadı; I got: could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Çalışmıyorsa tam yolu kullanın.
slhck

3

SSH anahtarlarınızın güvenliğini umursamıyorsanız, burada çok iyi yanıtlar var. Bunu yaparsanız, bulduğum en iyi cevap, yukarıdaki yorumdaki bir bağlantıdan diegocsandrim'in bu GitHub yorumuna olan bağlantıydı . Diğerlerinin bunu görme olasılığı daha yüksektir ve tam da bu repo ortadan kaybolursa, işte bu cevabın düzenlenmiş bir versiyonu:

Buradaki çoğu çözüm, görüntüde özel anahtarı bırakıyor. Görüntüye erişimi olan herkesin özel anahtarınıza erişimi olduğundan bu kötüdür. Davranışları hakkında yeterince bilgi sahibi squasholmadığımız için, anahtarı silseniz ve o katmanı ezmiş olsanız bile durum yine de böyle olabilir.

Aws s3 cli ile anahtara erişmek için bir ön imza URL'si üretiyoruz ve erişimi yaklaşık 5 dakika boyunca sınırlandırıyoruz, bu ön imza URL'sini repo dizinindeki bir dosyaya kaydediyoruz, ardından dockerfile içine görüntüye ekliyoruz.

Dockerfile dosyasında tüm bu adımları uygulayan bir RUN komutu var: ssh anahtarını almak, npm install komutunu çalıştırmak ve ssh anahtarını kaldırmak için ön şarkı URL'sini kullanın.

Bunu tek bir komutla yapmak ssh anahtarı herhangi bir katmanda saklanmaz, ancak ön işaret URL'si saklanır ve URL 5 dakika sonra geçerli olmayacağından bu bir sorun oluşturmaz.

Derleme betiği şöyle görünür:

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

Dockerfile şöyle görünür:

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
Bu çözümdeki sorun, pre_sign_url her seferinde değişeceğinden, Packages.json dosyasında değişiklik olmasa bile npm yüklemesinin önbelleğe alınamamasıdır. Anahtarı build.sh dosyasına almak ve bunu bir yapı argümanı olarak ayarlamak daha iyidir, böylece her seferinde değişmez
York Yang


3

Docker konteynırları içindeki SSH'nin zorluklarına kısa bir genel bakış burada detaylandırılmıştır . Sırları sızdırmadan bir kabın içinden güvenilir uzaktan kumandalara bağlanmak için birkaç yol vardır:

Bunların ötesinde, Compose kullanırken çalışma zamanında erişilebilen ayrı bir docker kapsayıcısında çalışan bir anahtar deposu kullanma olasılığı da vardır. Buradaki dezavantaj, Vault by HashiCorp gibi bir anahtar deposu oluşturmak ve yönetmek için gerekli makineler nedeniyle ek karmaşıklıktır .

Tek başına bir Docker kapsayıcısında SSH anahtar kullanımı için, yukarıdaki bağlantılara bakın ve özel ihtiyaçlarınıza bağlı olarak her birinin dezavantajlarını göz önünde bulundurun. Bununla birlikte, Compose içinde çalışıyorsanız ve bir uygulamayı çalışma zamanında bir anahtarla paylaşmak istiyorsanız (OP'nin pratikliklerini yansıtır) şunu deneyin:

  • Bir docker-compose.envdosya oluşturun ve dosyanıza ekleyin .gitignore.
  • Güncelleyin docker-compose.ymlve env_fileanahtarı gerektiren hizmete ekleyin .
  • Ortak anahtara, örneğin process.node.DEPLOYER_RSA_PUBKEYbir Node.js uygulaması durumunda , uygulama çalışma zamanında ortamdan erişin .

Yukarıdaki yaklaşım geliştirme ve test için idealdir ve üretim gereksinimlerini karşılayabilirken, üretimde yukarıda belirtilen diğer yöntemlerden birini daha iyi kullanabilirsiniz.

Ek kaynaklar:


3

Kapları oluşturmak için çok aşamalı yapı kullanabilirsiniz. Bu yaklaşım şunları yapabilirsiniz: -

Aşama 1 ssh ile görüntü oluşturma

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

2.Aşama: Konteynerinizi oluşturun

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

oluşturma dosyanıza env niteliğini ekleyin:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

daha sonra şu gibi komut dosyasından argümanlar iletin:

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

Ve güvenlik için ara kabı çıkarın. Bu şerefe yardımcı olacaktır.


2

Anahtarınızı bir Docker görüntü katmanına kaydetmeden veya ssh_agent jimnastikten geçmeden bunu başarmanın basit ve güvenli bir yolu:

  1. Bilgisayarınızdaki adımlardan biri olarak, aşağıdakileri ekleyerek Dockerfilebir .sshdizin oluşturun :

    RUN mkdir -p /root/.ssh

  2. Aşağıda, ssh dizinini bir birim olarak bağlamak istediğinizi gösterir:

    VOLUME [ "/root/.ssh" ]

  3. ssh_configBu satırı ekleyerek kabınızın genel anahtarları nerede bulacağını bildiğinden emin olun :

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

  4. Yerel kullanıcının .sshdizinini çalışma zamanında kapsayıcıya maruz bırakın :

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

    Veya dockerCompose.ymlbunu hizmetin ses seviyesi anahtarının altına ekleyin:

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

Nihai Dockerfilegibi bir şey içermelidir:

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

Sorunu başka bir şekilde çalışmaya çalışıyorum: bir görüntüye genel ssh anahtarı ekleme. Ama denemelerimde, "docker cp" nin bir konteynırdan bir ana bilgisayara kopyalamak olduğunu keşfettim. Creak tarafından cevap Madde 3 bir konteyner içine dosya enjekte docker cp kullanabilirsiniz diyor gibi görünüyor. Bkz. Https://docs.docker.com/engine/reference/commandline/cp/

alıntı

Bir kabın dosya sistemindeki dosyaları / klasörleri ana makine yoluna kopyalayın. Yollar, dosya sisteminin köküne göredir.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

Bu URL'nin bozuk olduğu anlaşılıyor.
slm

Bu eski veya yanlış. En geç 1.8.2'den itibaren her iki yönü de kopyalayabilir.
Jonathon Reinhart

1

Yetkili anahtarları, paylaşılan bir klasör kullanarak kabınıza iletebilir ve aşağıdaki gibi bir docker dosyası kullanarak izinleri ayarlayabilirsiniz:

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

Ve docker çalıştırmanız, ana bilgisayardaki bir yetkilendirme dizinini (authorised_keys'i tutarak) konteynerle paylaşmak için aşağıdakine benzer bir şey içerir ve daha sonra ana bilgisayardaki 7001 numaralı bağlantı noktasından erişilebilecek ssh portunu açar.

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

Bir kapta kabuk açmak ve bir kap içinde komut yürütmek için başka bir yol gibi görünen https://github.com/jpetazzo/nsenter adresine bakmak isteyebilirsiniz .


1

Kuşkusuz partiye geçtikten sonra, ana bilgisayar işletim sistemi anahtarlarınızı konteynerin içine kök salmaya hazır hale getirecek duruma ne dersiniz:

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

Kapsayı yinelemeleri özel anahtarları geride bırakabileceğinden, anahtarları yüklemek için Dockerfile kullanmaktan yana değilim.


0

Bir kabın çalışma zamanında ihtiyaç duyduğu hassas verileri yönetmek için sırları kullanabilirsiniz, ancak görüntüde veya kaynak kontrolünde depolamak istemezsiniz, örneğin:

  • Kullanıcı adları ve şifreler
  • TLS sertifikaları ve anahtarları
  • SSH anahtarları
  • Veritabanı veya dahili sunucunun adı gibi diğer önemli veriler
  • Genel dizeler veya ikili içerik (en fazla 500 kb boyutunda)

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

Çalışma zamanı (değil inşa) sırasında kullanmak için bir kap için imza anahtarları eklemek nasıl anlamaya çalışıyordu ve bu soru rastladı. Docker sırları kullanım durumum için bir çözüm gibi görünüyor ve kimse bundan bahsetmediği için ekleyeceğim.


0

Benim durumumda nodejs ve 'npm i' ile uzak bir depodan bir sorunum vardı. Ben 'düğüm' kullanıcı düğüm nodejs ve 700 ~ ~ .ssh konteyner ekledi düzeltildi.

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

liman işçisi-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

bundan sonra çalışmaya başladı


-1

En basit yol, bir launchpad hesabı edinin ve şunu kullanın: ssh-import-id


8
Soru özel anahtarlarla ilgiliydi. ssh-import-idyalnızca ortak anahtarları içeriyor gibi görünüyor.
cddr

-1

Çalışan bir docker kapsayıcısında, docker -i (etkileşimli) seçeneğiyle ssh-keygen düzenleyebilirsiniz. Bu, kapsayıcıyı anahtarın docker kapsayıcısında oluşturmasını ister.


1
Ve sonra ne? Bundan sonra hiçbir şey yapamazsınız, çünkü bunu yapma izniniz yok.
Jonathon Reinhart

-1

Debian / root / yetkili_anahtarları için:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.