Verwenden von SSH-Schlüsseln im Docker-Container


323

Ich habe eine App, die verschiedene lustige Dinge mit Git ausführt (wie das Ausführen von git clone & git push) und ich versuche, sie zu docken.

Ich stoße jedoch auf ein Problem, bei dem ich dem Container einen SSH-Schlüssel hinzufügen muss, damit der Container-Benutzer ihn verwenden kann.

Ich habe versucht, es zu kopieren /root/.ssh/, zu ändern $HOME, einen Git-SSH-Wrapper zu erstellen, und immer noch kein Glück.

Hier ist die Docker-Datei als Referenz:

#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 führt die git-Befehle wie aus git pull


3
Jeder, der sich dieser Frage nähert, sollte über das Endspiel nachdenken, da es einfach ist, eine Sicherheitslücke zu schaffen und diese hier zu vergessen, wenn Sie nicht vorsichtig sind. Lesen Sie alle Antworten und wählen Sie mit Bedacht aus.
Josh Habdas

Antworten:


143

Es ist ein schwierigeres Problem, wenn Sie SSH zur Erstellungszeit verwenden müssen. Zum Beispiel, wenn Sie verwenden git cloneoder in meinem Fall pipund npmaus einem privaten Repository herunterladen.

Die Lösung, die ich gefunden habe, besteht darin, Ihre Schlüssel mithilfe des --build-argFlags hinzuzufügen . Anschließend können Sie den neuen experimentellen --squashBefehl (hinzugefügt 1.13) verwenden, um die Ebenen zusammenzuführen, sodass die Schlüssel nach dem Entfernen nicht mehr verfügbar sind. Hier ist meine Lösung:

Befehl erstellen

$ 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

Update: Wenn Sie Docker 1.13 verwenden und experimentelle Funktionen verwenden, können Sie --squashan den Build-Befehl anhängen, mit dem die Ebenen zusammengeführt, die SSH-Schlüssel entfernt und ausgeblendet werden docker history.


13
Dieser GitHub-Problem-Thread weist darauf hin, dass dieser Ansatz immer noch nicht sicher ist. In diesem Kommentar finden Sie eine weitere ähnliche Lösung.
Eczajk

4
Eine andere Lösung anstelle des Quetschens besteht darin, den Schlüssel im selben RUN-Befehl hinzuzufügen und zu entfernen. Zwischen dem Hinzufügen und Entfernen verwenden Sie ihn für das, wofür Sie ihn benötigen.
Benjamin Hammer Nørgaard

2
Möglicherweise können Sie die Zeilen zum Erstellen der id_rsa.pubDatei entfernen, da dies nicht erforderlich ist.
LCB

1
Verwenden Sie anstelle des Quetschens mehrstufige Image-Builds .
Richard Kiefer

Wenn Ihr Schlüssel passwortgeschützt ist, verwenden Sie $(openssl rsa -in ~/.ssh/id_rsa)stattdessen
BroiSatse

89

Es stellt sich heraus, dass bei Verwendung von Ubuntu die ssh_config nicht korrekt ist. Sie müssen hinzufügen

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

zu Ihrer Docker-Datei, damit diese Ihren SSH-Schlüssel erkennt.


2
Sie müssen wahrscheinlich auch den richtigen Benutzernamen wie diesen einstellenRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone

1
Warum sollte jemand einen privaten Schlüssel von einem Host-Computer in einen Container kopieren? Befehl ist in Ordnung, aber ich sehe keinen Sinn darin, die oben genannten ...
Vladimir Djuricic

12
Das ist nicht sicher! In meiner Lösung unten finden Sie die neueste Version 1.13 von Docker. @ebensing
Daniel van Flymen

1
@VladimirDjuricic Es gibt jedoch Dinge wie Bereitstellungsschlüssel.
Zelphir Kaltstahl

Tatsächlich müssen Sie ssh-keygen -A ausführen, um ssh auf dem Ubuntu-Minimalcontainer ordnungsgemäß einzurichten. Dann können Sie Pub / Priv-Schlüssel hinzufügen und sshd starten. Ich habe diesen Eintrag in meiner Docker-Datei: 'RUN ssh-keygen -A' als einen der Schritte.
Piotrektt

83

Hinweis : Verwenden Sie diesen Ansatz nur für Bilder, die privat sind und immer sein werden !

Der SSH-Schlüssel bleibt im Bild gespeichert, auch wenn Sie den Schlüssel nach dem Hinzufügen in einem Ebenenbefehl entfernen (siehe Kommentare in diesem Beitrag ).

In meinem Fall ist das in Ordnung, also benutze ich Folgendes:

# 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
Dadurch bleibt Ihr Schlüssel im Bild, tun Sie es nicht.
CppLearner

12
@CppLearner Sie haben Recht, dies speichert den Schlüssel im Bild, und dies kann in einigen Fällen ein Sicherheitsproblem sein. Vielen Dank, dass Sie das hervorgehoben haben. Es gibt jedoch viele Situationen, in denen dies vollkommen sicher ist. Zum Beispiel für Bilder, die in einem privaten Repository gespeichert sind, oder Bilder, die direkt auf einem Produktionsserver erstellt wurden und die lokalen Schlüssel in das Bild kopieren.
Yellowcap

2
Wenn Sie Ihre Anbieter in der Docker-Datei installieren, hindert Sie nichts daran, den SSH-Schlüssel zu entfernen, sobald die Anbieter installiert sind.
SebScoFr

2
@SebScoFr, anscheinend werden die Schlüssel in einer der Ebenen gespeichert, auch wenn Sie sie in einem späteren Befehl entfernen (siehe Link in der aktualisierten Antwort). Das Bild zeigt also immer den SSH-Schlüssel an, und die Lösung sollte nur für private Bilder verwendet werden!
Yellowcap

1
@yellowcap nicht, wenn Sie - den Bau
zerstören

56

Wenn Sie Docker Compose verwenden , können Sie den SSH-Agenten einfach so weiterleiten:

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

23
Nur ein Hinweis, dass dies für Mac-Hosts nicht funktioniert, egal ob Docker-Computer (über VirtualBox) oder Docker für Mac (der xhyve verwendet), da die Unix-Domain-Sockets nicht als Proxy verwendet werden.
Joe Shaw

SSH_AUTH_SOCKist eine Variable, die einen Pfad zu einem SSH-Agenten enthält
Aistis


1
ssh-forwarding wird jetzt auch auf macOS-Hosts unterstützt - anstatt den Pfad von $SSH_AUTH_SOCKzu mounten, müssen Sie diesen Pfad mounten - /run/host-services/ssh-auth.sock.
Jakub Kukul

46

Erweiterung der Antwort von Peter Grainger Ich konnte den seit Docker 17.05 verfügbaren mehrstufigen Build verwenden . Offizielle Seite besagt:

Bei mehrstufigen Builds verwenden Sie mehrere FROMAnweisungen in Ihrer Docker-Datei. Jeder FROMBefehl kann eine andere Basis verwenden, und jeder von ihnen beginnt eine neue Phase des Builds. Sie können Artefakte selektiv von einer Stufe in eine andere kopieren und alles, was Sie nicht wollen, im endgültigen Bild zurücklassen.

Wenn ich dies hier berücksichtige, ist dies mein Beispiel für die Aufnahme von Dockerfiledrei Erstellungsphasen. Es soll ein Produktionsabbild der Client-Webanwendung erstellen.

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

.dockerignorewiederholt den Inhalt der .gitignoreDatei (verhindert, dass die node_modulesresultierenden distVerzeichnisse des Projekts kopiert werden):

.idea
dist
node_modules
*.log

Befehlsbeispiel zum Erstellen eines Images:

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

Wenn Ihr privater SSH-Schlüssel keine Passphrase hat, geben Sie einfach ein leeres SSH_KEY_PASSPHRASEArgument an.

So funktioniert es:

1). Nur in der ersten Phase package.jsonwerden yarn.lockDateien und der private SSH-Schlüssel in das erste benannte Zwischenbild kopiert sources. Um weitere Eingabeaufforderungen für SSH-Schlüssel zu vermeiden, wird diese automatisch hinzugefügt ssh-agent. Schließlich yarninstalliert der Befehl alle erforderlichen Abhängigkeiten von NPM und klont private Git-Repositorys von Bitbucket über SSH.

2). In der zweiten Phase wird der Quellcode der Webanwendung erstellt, minimiert und im distVerzeichnis des nächsten benannten Zwischenabbilds abgelegt production. Beachten Sie, dass der Quellcode der installierten node_modulesDatei aus dem sourcesin der ersten Phase erstellten Image mit der folgenden Zeile kopiert wird:

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

Wahrscheinlich könnte es auch die folgende Zeile sein:

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

Wir haben hier nur noch das node_modulesVerzeichnis vom ersten Zwischenbild, nein SSH_KEYund SSH_KEY_PASSPHRASEArgumente mehr. Der gesamte Rest, der für die Erstellung benötigt wird, wird aus unserem Projektverzeichnis kopiert.

3). In der dritten Stufe reduzieren wir die Größe des endgültigen Images, das als gekennzeichnet wird, ezze/geoport:0.6.0indem wir nur das distVerzeichnis des zweiten Zwischenabbilds mit dem Namen einschließen productionund Node Express zum Starten eines Webservers installieren.

Das Auflisten von Bildern ergibt eine Ausgabe wie folgt:

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

Dabei entsprechen nicht markierte Bilder der ersten und der zweiten Zwischenstufe.

Wenn du läufst

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

Sie werden keine Erwähnungen von SSH_KEYund SSH_KEY_PASSPHRASEim endgültigen Bild sehen.


Alter Beitrag, aber ich möchte betonen, dass dies bei weitem der beste Weg ist, dies vor dem 18.09. Zu tun. Squash ist unnötig und risikobehaftet. Mit Multi-Stage wissen Sie, dass Sie nur die gewünschten Artefakte einbringen. Stellen Sie sich Squash als Deaktivierung der Dateien vor, die Sie nicht möchten, und mehrstufig als Deaktivierung. Diese Antwort muss höher sein. Das Backen Ihrer SSH-Schlüssel im Bild ist eine schreckliche Übung.
Mritalian

@ezze Vielen Dank für diesen sehr nützlichen Beitrag :) SSH-Agent macht mich verrückt, ich habe etwas Ähnliches gemacht wie du: Ich sehe in Docker-Build-Protokollen richtig, Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)aber wenn ich einen anderen RUN oder sogar denselben RUN einchecke Befehl durch Ausführen eines Befehls ssh-add -lsagt mir, dass "Der Agent hat keine Identität". Fangen Sie an, mir die Haare abzuziehen, irgendwelche Gedanken?
Alex

40

Um Ihren SSH-Schlüssel in einen Container zu injizieren, haben Sie mehrere Lösungen:

  1. Wenn Sie eine Docker-Datei mit der ADDAnweisung verwenden, können Sie diese während des Erstellungsprozesses einfügen

  2. Einfach so etwas machen cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Verwenden des docker cpBefehls, mit dem Sie Dateien einfügen können, während ein Container ausgeführt wird.


2
Ab sofort habe ich versucht, es in /root/.ssh/id_rsa zu kopieren, erhalte aber weiterhin die Fehlermeldung "Überprüfung des Hostschlüssels fehlgeschlagen. Schwerwiegend: Das Remote-Ende hat unerwartet aufgelegt", was ich ziemlich sicher meine verwendet den Schlüssel aus irgendeinem Grund nicht. Ich denke also, dass ich noch etwas tun muss, um das System tatsächlich anzuweisen, es als SSH-Schlüssel zu verwenden? Ich weiß nicht genau, wie ich dieses debuggen soll. (und ich weiß, dass dieser Schlüssel funktioniert, weil er ohne
Probleme

Können Sie sicherstellen, dass / etc / ssh / ssh_config auf die richtige Schlüsseldatei abzielt?
Knarren

1
Gibt es eine gute Möglichkeit, die Dateien des Docker-Containers zu überprüfen? Oder sollte ich einfach versuchen, eine gültige Konfiguration zu kopieren?
Ebensing

3
Ich habe es gerade mit ' apt-get install openssh-serverBasis' -Image versucht , meinen Schlüssel in /root/.ssh/id_rsa eingegeben und es hat gut funktioniert. Welches Bild verwenden Sie?
Knarren

Wenn Sie die Datei eines Containers überprüfen müssen, ist es am besten, das resultierende Image mit 'cat' festzuschreiben und auszuführen.
Knarren

15

Eine plattformübergreifende Lösung besteht darin, einen Bind-Mount zu verwenden, um den .sshOrdner des Hosts für den Container freizugeben:

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

Ähnlich wie bei der Agentenweiterleitung werden durch diesen Ansatz die öffentlichen Schlüssel für den Container zugänglich. Ein weiterer Vorteil ist, dass es auch mit einem Nicht-Root-Benutzer funktioniert und Sie mit GitHub verbunden werden. Eine Einschränkung ist jedoch, dass alle Inhalte (einschließlich privater Schlüssel) aus dem .sshOrdner gemeinsam genutzt werden, sodass dieser Ansatz nur für die Entwicklung und nur für vertrauenswürdige Container-Images wünschenswert ist.


1
Dies könnte funktionieren, aber nicht docker buildnur währenddocker run
Alexander Mills

3
Genau darum geht es. Sie möchten Ihre SSH-Schlüssel nicht in eine Docker-Datei einfügen.
Mohammad Azim

2
Da die Weiterleitung von SSH-Agenten außerhalb von Linux nicht funktioniert, ist dies eine gute Lösung, um in einer Entwicklungsumgebung ohne großen Aufwand einsatzbereit zu sein.
Josh Habdas

Ich verwende Docker docker-compose upin meinem lokalen Windows 10. Wie soll ich Ihre Lösung in diesem Szenario verwenden?
Laaalu

Im Wesentlichen fragen Sie, wie das Volume in Docker Compose zugeordnet werden soll. Oben gibt es eine Antwort darauf. Speziell für Windows könnte dies helfen, stackoverflow.com/questions/41334021/…
Mohammad Azim

14

Docker-Container sollten als eigene "Dienste" angesehen werden. Um Bedenken zu trennen, sollten Sie Funktionen trennen:

1) Daten sollten sich in einem Datencontainer befinden: Verwenden Sie ein verknüpftes Volume, um das Repo zu klonen. Dieser Datencontainer kann dann mit dem Dienst verknüpft werden, der ihn benötigt.

2) Verwenden Sie einen Container, um die Git-Klonaufgabe auszuführen (dh der einzige Job ist das Klonen), indem Sie den Datencontainer beim Ausführen mit ihm verknüpfen.

3) Gleiches gilt für den SSH-Schlüssel: Legen Sie fest, dass es sich um ein Volume handelt (wie oben vorgeschlagen), und verknüpfen Sie es bei Bedarf mit dem Git-Klon-Dienst

Auf diese Weise sind sowohl die Klonaufgabe als auch der Schlüssel kurzlebig und nur bei Bedarf aktiv.

Wenn Ihre App selbst eine Git-Oberfläche ist, sollten Sie Github- oder Bitbucket-REST-APIs direkt in Betracht ziehen, um Ihre Arbeit zu erledigen: Dafür wurden sie entwickelt.


13

Diese Zeile ist ein Problem:

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

Wenn Sie die Dateien angeben, die Sie in das Bild kopieren möchten, können Sie nur relative Pfade verwenden - relativ zu dem Verzeichnis, in dem sich Ihre Docker-Datei befindet. Sie sollten stattdessen Folgendes verwenden:

ADD id_rsa /root/.ssh/id_rsa

Legen Sie die Datei id_rsa in demselben Verzeichnis ab, in dem sich Ihre Docker-Datei befindet.

Weitere Informationen finden Sie hier: http://docs.docker.io/reference/builder/#add


4
Dies ist auch ein Sicherheitsproblem, da ein privater Schlüssel in ein Bild eingefügt wird, das leicht vergessen werden kann.
Mike D

docker cplegt es einfach in den Behälter und nicht in das Bild, oder?
Alexander Mills

13

Wir hatten ein ähnliches Problem bei der Installation von npm in der Docker-Erstellungszeit.

Inspiriert von der Lösung von Daniel van Flymen und der Kombination mit dem Umschreiben von Git- URLs haben wir eine etwas einfachere Methode zur Authentifizierung der npm-Installation von privaten Github-Repos gefunden - wir haben oauth2-Token anstelle der Schlüssel verwendet.

In unserem Fall wurden die npm-Abhängigkeiten als "git + https://github.com/ ..." angegeben.

Für die Authentifizierung im Container müssen die URLs neu geschrieben werden, damit sie entweder für die SSH-Authentifizierung (ssh: //git@github.com/) oder die Token-Authentifizierung (https: // $ {GITHUB_TOKEN} @ github.com /) geeignet sind.

Build-Befehl:

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

Leider bin ich auf Docker 1.9, daher ist die Option --squash noch nicht vorhanden und muss eventuell hinzugefügt werden

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

Leiten Sie den SSH-Authentifizierungssocket an den Container weiter:

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

Ihr Skript kann a ausführen git clone.

Extra: Wenn geklonte Dateien zu einem bestimmten Benutzer gehören sollen, müssen Sie sie verwenden, chownda die Verwendung eines anderen Benutzers als root im Container gitfehlschlägt.

Sie können diese Veröffentlichung in der Containerumgebung einige zusätzliche Variablen durchführen:

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

Nachdem Sie geklont haben, müssen Sie ausführen chown $OWNER_USER:$OWNER_GROUP -R <source_folder>, um den richtigen Besitz festzulegen, bevor Sie den Container verlassen, damit ein Nicht-Root-Benutzer außerhalb des Containers auf die Dateien zugreifen kann.


1
In neueren Docker-Versionen können Sie festlegen -u root:$(id -u $USER), dass mindestens die Dateien derselben primären Gruppe wie Ihr Benutzer gehören. Dadurch sollten alle Dateien zumindest lesbar sein, ohne sudodass sie mit 0600Berechtigungen erstellt werden.
Dragon788

@ dragon788 Ich denke du hast einen Tippfehler: -u root:$(id -u $USER)sollte sein -g.
Edupo

Guter Anruf! Ich scheine nicht in der Lage zu sein, das Problem vom Handy aus zu beheben. Ich werde es bald auf dem Desktop versuchen.
Dragon788

Ich habe es /tmp/ssh_auth.sock: No such file or directoryjetzt /tmp/ssh-vid8Zzi8UILE/agent.46016auf meinem Host-Computer
vladkras

@vladkras der Fehler ist ziemlich allgemein. Kann durch Berechtigungen /tmpin Ihrem Container verursacht werden. Oder ein Tippfehler im Docker-Befehl run. Stellen Sie sicher, dass die bind-Anweisung korrekt ist -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: Reihenfolge ist wichtig und Semikolon ist ebenfalls wichtig. Weitere Hilfe finden Sie in der Docker-Dokumentation .
Edupo

10

Wie eczajk bereits in Daniel van Flymens Antwort kommentierte, scheint es nicht sicher zu sein, die Schlüssel zu entfernen und zu verwenden --squash, da sie in der Geschichte immer noch sichtbar sind (docker history --no-trunc ).

Stattdessen können Sie mit Docker 18.09 jetzt die Funktion "Geheimnisse erstellen" verwenden. In meinem Fall habe ich ein privates Git-Repo mit dem SSH-Schlüssel meines Hosts mit den folgenden Angaben in meiner Docker-Datei geklont:

# syntax=docker/dockerfile:experimental

[...]

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

[...]

Um dies verwenden zu können, müssen Sie das neue BuildKit-Backend aktivieren, bevor Sie Folgendes ausführen können docker build:

export DOCKER_BUILDKIT=1

Und Sie müssen den --ssh defaultParameter hinzufügen docker build.

Weitere Informationen hierzu finden Sie hier: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
Beste Lösung IMHO. Ich musste zwei weitere Dinge tun, um es zum ssh-add ~/.ssh/id_rsaLaufen zu bringen: 1) Füge meinen privaten Schlüssel zu ssh-agent hinzu und 2) füge den Git-Host zu bekannten_Hosts hinzu, dh für Bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Moritz Ringler

Ich habe das überhaupt nicht zum Laufen gebracht. Ich erhalte immer noch Berechtigungsfehler: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.Dies trotz Übergabe des --ssh defaultFlags in meinem Docker-Build und Verwendung --mount=type=sshim Befehl run, in dem ich git clone. Ich kann das gleiche Repo problemlos auf der Build-Maschine klonen. Im Docker-Build-Container schlägt dies einfach fehl. Ich vermute, dass die Mac-Version von Docker den SSH-Client nicht weitergibt.
PMende

@PMende konnten Sie dieses von Ihnen erwähnte Problem herausfinden, da ich auch vor dem gleichen Problem stehe.
Sadan A.

@SadanArshad Es stellt sich heraus, dass diese Funktionalität derzeit nur unterstützt wird, wenn Sie Docker von einem Linux-Computer ausführen. Es funktioniert nicht, wenn Sie Ihre Docker-Befehle von einem Mac aus ausführen (und wahrscheinlich auch von Windows, obwohl ich dies nicht bestätigen kann).
PMende

Schade, dass das mit Docker-Compose nicht funktioniert ... github.com/docker/compose/issues/6440
Alexis Wilke

9

Dieses Problem ist wirklich ärgerlich. Da Sie keine Datei außerhalb des Dockerfile-Kontexts hinzufügen / kopieren können, ist es unmöglich, ~ / .ssh / id_rsa einfach mit /root/.ssh/id_rsa des Bildes zu verknüpfen, und wenn Sie definitiv einen Schlüssel benötigen, um etwas zu tun wie Git-Klon von einem privaten Repo-Link ..., während der Erstellung Ihres Docker-Images.

Wie auch immer, ich habe eine Lösung gefunden, die nicht so überzeugend war, aber für mich funktioniert hat.

  1. in Ihrer Docker-Datei:

    • Fügen Sie diese Datei als /root/.ssh/id_rsa hinzu
    • mach was du willst, wie Git Clone, Komponist ...
    • rm /root/.ssh/id_rsa am Ende
  2. ein Skript für einen Dreh:

    • cp Ihren Schlüssel zu dem Ordner mit Docker-Datei
    • Docker bauen
    • rm der kopierte Schlüssel
  3. Wenn Sie aus diesem Image einen Container mit einigen SSH-Anforderungen ausführen müssen, fügen Sie einfach -v für den Befehl run hinzu, z.

    Docker führen Sie den Befehl -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa --name container image aus

Diese Lösung führt dazu, dass sowohl in Ihrer Projektquelle als auch im erstellten Docker-Image kein privater Schlüssel vorhanden ist.


1
"Da Sie keine Datei außerhalb des Dockerfile-Kontexts hinzufügen / kopieren können", haben Sie gesehen docker cp? Es wird verwendet, um "Dateien / Ordner zwischen einem Container und Ihrem Host zu kopieren".
Jonathon Reinhart

@ JonathonReinhart, danke, dass du darauf hingewiesen hast. Ja, docker cpkönnte den Trick machen. In genau dieser Situation brauchte ich jedoch den ssh_key, während das Image erstellt wurde, und es gibt zu diesem Zeitpunkt keinen Container ... wird meinen unklaren Ausdruck trotzdem aktualisieren, danke.
ImLeo

9

Ich bin heute auf das gleiche Problem gestoßen und habe die Version mit früheren Beiträgen etwas modifiziert. Ich fand diesen Ansatz für mich nützlicher

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

(Beachten Sie, dass das schreibgeschützte Flag, damit der Container meinen SSH-Schlüssel auf keinen Fall durcheinander bringt.)

Im Container kann ich jetzt laufen:

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

Ich bekomme also nicht den Bad owner or permissions on /root/.ssh/..Fehler, der von @kross notiert wurde


Vielen Dank! Dies war der Schlüssel, damit es für mich funktioniert: ssh-agent und ssh-add in einem einzigen Befehl wie : ssh-agent bash -c "ssh-add...". Ich kann das dann direkt an Docker Run übergeben. Alle vorherigen Beispiele, die ich gefunden habe, wurden verwendet eval ssh-agent, gefolgt von ssh-add, und ich konnte keinen Weg finden, dies evalüber den Docker-Befehl run auszuführen.
Ryanman


6

Sie können auch Ihr .ssh-Verzeichnis zwischen dem Host und dem Container verknüpfen. Ich weiß nicht, ob diese Methode Auswirkungen auf die Sicherheit hat, aber möglicherweise die einfachste Methode. So etwas sollte funktionieren:

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

Denken Sie daran, dass Docker mit sudo ausgeführt wird (es sei denn, Sie tun dies nicht). In diesem Fall verwenden Sie die Root-SSH-Schlüssel.


Die Verwendung dieser Methode funktioniert mit Docker 0.11. Wenn Sie jedoch fig verwenden, wird ein Panikfehler ausgelöst. Ich weiß nicht warum
Luis Elizondo

3
Dies wäre eine bevorzugte Methode. Der Trick wäre, die Schlüssel meines nicht privilegierten Hostbenutzers als Stammverzeichnis des Containers zu verwenden. Wie Sie bereits erwähnt haben, versucht dies nicht so, wie es der Host-Root-Benutzer vorgibt Bad owner or permissions on /root/.ssh/config.
Kross

Dies kann nur während docker run, aber nicht während verwendet werden docker build.
ccpizza

3
@ccpizza, ich sehe das als Vorteil. Bei vielen dieser Antworten bleiben private Schlüssel in einem Bild gespeichert. Der Schlüssel bleibt auch nach dem Entfernen des Schlüssels in einem nachfolgenden Ebenenbefehl gespeichert. Durch die Einführung der privaten Schlüssel nur während der Ausführung (nicht während der Erstellung) können sie nur im Container (nicht im Image) vorhanden sein.
Cowlinator

6

Ausgehend von docker API 1.39+(API-Version docker versionprüfen mit ) Docker-Build ermöglicht das--ssh Option entweder mit einem Agent-Socket oder mit Schlüsseln verwendet werden, damit die Docker Engine SSH-Agentenverbindungen weiterleiten kann.

Build-Befehl

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

Mehr Info:


1
Die Tilde-Erweiterung hat bei mir nicht funktioniert; Ich habe : could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Verwenden Sie den vollständigen Pfad, wenn dies nicht funktioniert.
Slhck

3

Wenn Sie sich nicht um die Sicherheit Ihrer SSH-Schlüssel kümmern, finden Sie hier viele gute Antworten. Wenn Sie dies tun, war die beste Antwort, die ich gefunden habe, ein Link in einem Kommentar oben zu diesem GitHub-Kommentar von diegocsandrim . Damit andere es eher sehen und für den Fall, dass das Repo jemals verschwindet, hier eine bearbeitete Version dieser Antwort:

Die meisten Lösungen lassen den privaten Schlüssel im Bild. Dies ist schlecht, da jeder, der Zugriff auf das Bild hat, Zugriff auf Ihren privaten Schlüssel hat. Da wissen wir nicht genug über das Verhalten vonsquash , kann dies auch dann der Fall sein, wenn Sie den Schlüssel löschen und diese Ebene quetschen.

Wir generieren eine Pre-Sign-URL für den Zugriff auf den Schlüssel mit aws s3 cli und beschränken den Zugriff für ca. 5 Minuten. Wir speichern diese Pre-Sign-URL in einer Datei im Repo-Verzeichnis und fügen sie dann in der Docker-Datei dem Bild hinzu.

In Dockerfile haben wir einen RUN-Befehl, der alle folgenden Schritte ausführt: Verwenden Sie die Pre-Sing-URL, um den SSH-Schlüssel abzurufen, führen Sie die npm-Installation aus und entfernen Sie den SSH-Schlüssel.

Wenn Sie dies in einem einzigen Befehl tun, wird der SSH-Schlüssel in keiner Ebene gespeichert, aber die Vorzeichen-URL wird gespeichert. Dies ist kein Problem, da die URL nach 5 Minuten nicht mehr gültig ist.

Das Build-Skript sieht folgendermaßen aus:

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

Dockerfile sieht folgendermaßen aus:

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
Das Problem bei dieser Lösung besteht darin, dass die npm-Installation nicht zwischengespeichert werden kann, da sich die Datei packages.json nicht ändert, da sich pre_sign_url jedes Mal ändert. Es ist besser, den Schlüssel in der build.sh zu bekommen und ihn als Build-Argument festzulegen, damit er sich nicht jedes Mal ändert
York Yang


3

Eine kurze Übersicht über die Herausforderungen von SSH in Docker-Containern finden Sie hier . Es gibt verschiedene Möglichkeiten, um innerhalb eines Containers eine Verbindung zu vertrauenswürdigen Fernbedienungen herzustellen, ohne Geheimnisse preiszugeben:

Darüber hinaus besteht die Möglichkeit, einen Schlüsselspeicher zu verwenden, der in einem separaten Docker-Container ausgeführt wird, auf den zur Laufzeit bei Verwendung von Compose zugegriffen werden kann. Der Nachteil hierbei ist die zusätzliche Komplexität aufgrund der Maschinen, die zum Erstellen und Verwalten eines Schlüsselspeichers wie Vault von HashiCorp erforderlich sind .

Informationen zur Verwendung von SSH-Schlüsseln in einem eigenständigen Docker-Container finden Sie in den oben verlinkten Methoden. Berücksichtigen Sie die jeweiligen Nachteile je nach Ihren spezifischen Anforderungen. Wenn Sie jedoch in Compose ausgeführt werden und zur Laufzeit einen Schlüssel für eine App freigeben möchten (dies spiegelt die praktischen Aspekte des OP wider), versuchen Sie Folgendes:

  • Erstellen Sie eine docker-compose.envDatei und fügen Sie sie Ihrer .gitignoreDatei hinzu.
  • Aktualisieren Sie Ihre docker-compose.ymlund fügen Sie sie env_filefür den Service hinzu, für den der Schlüssel erforderlich ist.
  • Zugriff auf den öffentlichen Schlüssel aus der Umgebung zur Laufzeit der Anwendung, z. B. process.node.DEPLOYER_RSA_PUBKEYim Fall einer Node.js-Anwendung.

Der oben beschriebene Ansatz ist ideal für die Entwicklung und das Testen. Obwohl er die Produktionsanforderungen erfüllen könnte, ist es in der Produktion besser, eine der anderen oben genannten Methoden zu verwenden.

Zusätzliche Ressourcen:


3

Sie können einen mehrstufigen Build verwenden, um Container zu erstellen Dies ist der folgende Ansatz: -

Stufe 1 Erstellen eines Bildes mit 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

Stufe 2: Bauen Sie Ihren Container

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

Fügen Sie in Ihrer Erstellungsdatei das env-Attribut hinzu:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

Übergeben Sie dann Argumente aus dem Build-Skript wie folgt:

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

Und entfernen Sie den Zwischenbehälter aus Sicherheitsgründen. Dies wird Ihnen helfen, zu jubeln.


2

Ein einfacher und sicherer Weg, dies zu erreichen, ohne Ihren Schlüssel in einer Docker-Bildebene zu speichern oder ssh_agent-Gymnastik zu durchlaufen, ist:

  1. DockerfileErstellen Sie als einen Ihrer Schritte ein .sshVerzeichnis, indem Sie Folgendes hinzufügen:

    RUN mkdir -p /root/.ssh

  2. Darunter geben Sie an, dass Sie das ssh-Verzeichnis als Volume bereitstellen möchten:

    VOLUME [ "/root/.ssh" ]

  3. Stellen Sie sicher, dass Ihr Container ssh_configweiß, wo sich die öffentlichen Schlüssel befinden, indem Sie diese Zeile hinzufügen:

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

  4. Stellen Sie das .sshVerzeichnis Ihres lokalen Benutzers zur Laufzeit dem Container zur Verfügung:

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

    Oder dockerCompose.ymlfügen Sie dies unter der Lautstärketaste des Dienstes hinzu:

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

Dein Finale Dockerfilesollte etwas enthalten wie:

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

Ich versuche, das Problem anders zu lösen: Hinzufügen eines öffentlichen SSH-Schlüssels zu einem Bild. In meinen Versuchen habe ich jedoch festgestellt, dass "Docker-CP" zum Kopieren von einem Container auf einen Host dient. Punkt 3 in der Antwort von Creak scheint zu sagen, dass Sie Docker CP verwenden können, um Dateien in einen Container zu injizieren. Siehe https://docs.docker.com/engine/reference/commandline/cp/

Auszug

Kopieren Sie Dateien / Ordner aus dem Dateisystem eines Containers in den Hostpfad. Pfade sind relativ zum Stammverzeichnis des Dateisystems.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

Diese URL scheint jetzt kaputt zu sein.
Slm

Dies ist veraltet oder falsch. Es kann beide Richtungen ab spätestens 1.8.2 kopieren.
Jonathon Reinhart

1

Sie können die autorisierten Schlüssel mithilfe eines freigegebenen Ordners an Ihren Container übergeben und die Berechtigungen mithilfe einer Docker-Datei wie folgt festlegen:

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

Und Ihr Docker-Lauf enthält etwa Folgendes, um ein Auth-Verzeichnis auf dem Host (mit den autorisierten Schlüsseln) für den Container freizugeben und dann den SSH-Port zu öffnen, auf den über Port 7001 auf dem Host zugegriffen werden kann.

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

Möglicherweise möchten Sie sich https://github.com/jpetazzo/nsenter ansehen. Dies scheint eine weitere Möglichkeit zu sein, eine Shell in einem Container zu öffnen und Befehle in einem Container auszuführen.


1

Zugegeben, zu spät zur Party, wie wäre es damit, wenn die Schlüssel Ihres Host-Betriebssystems im laufenden Betrieb zum Rooten im Container verfügbar werden:

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

Ich bin nicht dafür, Dockerfile zum Installieren von Schlüsseln zu verwenden, da Iterationen Ihres Containers möglicherweise private Schlüssel zurücklassen.


0

Sie können Geheimnisse verwenden, um vertrauliche Daten zu verwalten, die ein Container zur Laufzeit benötigt, die Sie jedoch nicht im Image oder in der Quellcodeverwaltung speichern möchten, z.

  • Benutzernamen und Passwörter
  • TLS-Zertifikate und Schlüssel
  • SSH-Schlüssel
  • Andere wichtige Daten wie der Name einer Datenbank oder eines internen Servers
  • Generische Zeichenfolgen oder binäre Inhalte (bis zu 500 KB groß)

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

Ich habe versucht herauszufinden, wie man einem Container Signaturschlüssel hinzufügt, um sie zur Laufzeit zu verwenden (nicht zu erstellen), und bin auf diese Frage gestoßen. Docker-Geheimnisse scheinen die Lösung für meinen Anwendungsfall zu sein, und da es noch niemand erwähnt hat, werde ich es hinzufügen.


0

In meinem Fall hatte ich ein Problem mit nodejs und 'npm i' aus einem Remote-Repository. Ich habe behoben, dass 'node' user zu nodejs container und 700 zu ~ / .ssh im container hinzugefügt wurde.

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

danach hat es angefangen zu funktionieren


-1

Am einfachsten ist es, ein Launchpad-Konto zu erstellen und Folgendes zu verwenden: ssh-import-id


8
Die Frage betraf private Schlüssel. ssh-import-idEs sieht so aus, als würde es nur öffentliche Schlüssel importieren.
CDD

-1

In einem laufenden Docker-Container können Sie ssh-keygen mit der Option docker -i (interaktiv) ausgeben. Dadurch werden die Eingabeaufforderungen des Containers weitergeleitet, um den Schlüssel im Docker-Container zu erstellen.


1
Und dann was? Danach können Sie nichts mehr tun, da Sie keine Berechtigung dazu haben.
Jonathon Reinhart

-1

Für debian / root / authorized_keys:

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

RUN mkdir /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN  echo "ssh-rsa AAAA....yP3w== rsa-key-project01" >> /root/.ssh/authorized_keys
RUN chmod -R go= /root/.ssh
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.