486 Stimmen

Verwendung von SSH-Schlüsseln innerhalb eines Docker-Containers

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

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

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

Hier ist das Dockerfile zur 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 git pull aus

246voto

Daniel van Flymen Punkte 9809

Es ist ein schwierigeres Problem, wenn Sie SSH zur Build-Zeit verwenden müssen. Zum Beispiel, wenn Sie git clone verwenden oder in meinem Fall pip und npm zum Herunterladen aus einem privaten Repository.

Die Lösung, die ich gefunden habe, besteht darin, Ihre Schlüssel mit dem Flag --build-arg hinzuzufügen. Dann können Sie den neuen experimentellen Befehl --squash (hinzugefügt in 1.13) verwenden, um die Schichten zu fusionieren, sodass die Schlüssel nach dem Entfernen nicht mehr verfügbar sind. Hier ist meine Lösung:

Build-Befehl

$ docker build -t beispiel --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

# SSH-Host autorisieren
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh
# Siehe: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints
COPY known_hosts > /root/.ssh/known_hosts

# Schlüssel hinzufügen und Berechtigungen setzen
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

# Cache-Löschung vermeiden, indem Anforderungen zuerst hinzugefügt werden
ADD ./requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

# SSH-Schlüssel entfernen
RUN rm -rf /root/.ssh/

# Restliche Dateien hinzufügen
ADD . .

CMD python manage.py runserver

Aktualisierung: Wenn Sie Docker 1.13 verwenden und experimentelle Funktionen aktiviert haben, können Sie --squash dem Build-Befehl anhängen, der die Schichten fusioniert, die SSH-Schlüssel entfernt und sie vor docker history verbirgt.

104voto

ebensing Punkte 6023

Es stellt sich heraus, dass bei der 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 Dockerdatei, um es zu erkennen Ihr SSH-Schlüssel.

97voto

yellowcap Punkte 3867

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

Der ssh-Schlüssel bleibt im Bild gespeichert, auch wenn Sie den Schlüssel in einem Layer-Befehl entfernen, nachdem Sie ihn hinzugefügt haben (siehe Kommentare in diesem Beitrag).

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

# Einrichtung für ssh auf 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

94voto

Aistis Punkte 3272

Wenn Sie Docker Compose verwenden, ist eine einfache Möglichkeit, den SSH-Agenten wie folgt weiterzuleiten:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Lokalen SSH-Schlüssel der Maschine an Docker weiterleiten
    environment:
        SSH_AUTH_SOCK: /ssh-agent

oder äquivalent, wenn docker run verwendet wird:

$ docker run --mount type=bind,source=$SSH_AUTH_SOCK,target=/ssh-agent \
             --env SSH_AUTH_SOCK=/ssh-agent \
             some-image

74voto

ezze Punkte 3796

Durch die Erweiterung von Peter Graingers Antwort konnte ich das Mehrschicht-Build nutzen, das seit Docker 17.05 verfügbar ist. Die offizielle Seite besagt:

Mit Mehrschicht-Builds verwendest du mehrere FROM-Anweisungen in deinem Dockerfile. Jede FROM-Anweisung kann eine unterschiedliche Basis verwenden, und jede davon startet eine neue Stufe des Builds. Du kannst Artefakte selektiv von einer Stufe zur anderen kopieren und dabei alles zurücklassen, was du nicht im endgültigen Bild haben möchtest.

Unter Berücksichtigung dessen ist hier mein Beispiel eines Dockerfile mit drei Build-Stufen. Es soll ein Produktionsbild der Client-Webanwendung erstellen.

# Stufe 1: Quellen von npm und git über SSH erhalten
FROM node:carbon AS Quellen
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/

# Stufe 2: Bau des minimierten Produktionscodes
FROM node:carbon AS Produktion
WORKDIR /app/
COPY --from=Quellen /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stufe 3: Enthält nur erstellte Produktionsdateien und hostet sie mit Node Express Server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=Produktion /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignore wiederholt die Inhalte der .gitignore Datei (es verhindert das Kopieren der Verzeichnisse node_modules und dist des Projekts):

.idea
dist
node_modules
*.log

Beispielbefehl zum Erstellen eines Bildes:

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

Wenn dein privater SSH-Schlüssel keine Passphrase hat, gib einfach das leere SSH_KEY_PASSPHRASE Argument an.

So funktioniert es:

1). In der ersten Stufe werden nur die Dateien package.json, yarn.lock Dateien und der private SSH-Schlüssel in das erste Zwischenbild namens Quellen kopiert. Um weitere Passwortabfragen für den SSH-Schlüssel zu vermeiden, wird er automatisch zu ssh-agent hinzugefügt. Schließlich installiert der yarn Befehl alle erforderlichen Abhängigkeiten von NPM und klonen private Git-Repositories von Bitbucket über SSH.

2). Die zweite Stufe baut und minimiert den Quellcode der Webanwendung und platziert ihn im dist Verzeichnis des nächsten Zwischenbildes namens Produktion. Beachte, dass der Quellcode der installierten node_modules vom Bild namens Quellen kopiert wird, das in der ersten Stufe erzeugt wurde, durch diese Zeile:

COPY --from=Quellen /app/ /app/

Es könnte auch die folgende Zeile sein:

COPY --from=Quellen /app/node_modules/ /app/node_modules/

Hier haben wir nur das Verzeichnis node_modules aus dem ersten Zwischenbild, keine SSH_KEY und SSH_KEY_PASSPHRASE Argumente mehr. Alle restlichen für den Build erforderlichen Dateien werden aus unserem Projektverzeichnis kopiert.

3). In der dritten Stufe reduzieren wir die Größe des endgültigen Bildes, das als ezze/geoport:0.6.0 getaggt wird, indem nur das dist Verzeichnis aus dem zweiten Zwischenbild namens Produktion und das Installieren von Node Express für das Starten eines Webservers enthalten ist.

Das Auflisten der Bilder ergibt eine Ausgabe wie diese:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        vor 3 Stunden       717MB
                            1f6518644324        vor 3 Stunden       1.1GB
                            fa00f1182917        vor 4 Stunden       1.63GB
node                carbon              b87c2ad8344d        vor 4 Wochen        676MB

wo nicht getaggte Bilder den ersten und den zweiten Zwischenbaustufen entsprechen.

Wenn du

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

ausführst, wirst du keine Erwähnungen von SSH_KEY und SSH_KEY_PASSPHRASE im endgültigen Bild sehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X