Ich habe kürzlich mit Docker experimentiert, um einige Dienste zu entwickeln, mit denen ich herumspielen kann, und eine Sache, die mich immer wieder nervt, ist das Einfügen von Passwörtern in eine Docker-Datei. Ich bin ein Entwickler, daher fühlt sich das Speichern von Passwörtern in der Quelle wie ein Schlag ins Gesicht an. Sollte dies überhaupt ein Problem sein? Gibt es gute Konventionen zum Umgang mit Passwörtern in Dockerfiles?
162
Antworten:
Auf jeden Fall ist es ein Problem. Docker-Dateien werden normalerweise in Repositorys eingecheckt und mit anderen Personen geteilt. Eine Alternative besteht darin, zur Laufzeit alle Anmeldeinformationen (Benutzernamen, Kennwörter, Token usw.) als Umgebungsvariablen bereitzustellen . Dies ist über das
-e
Argument (für einzelne--env-file
Variablen in der CLI) oder das Argument (für mehrere Variablen in einer Datei) möglichdocker run
. Lesen Sie dies für die Verwendung von Umwelt mit Docker-Compose.Die Verwendung
--env-file
ist definitiv eine sicherere Option, da dies vor den Geheimnissen schützt, die bei Verwendung inps
oder in Protokollen auftauchenset -x
.Umgebungsvariablen sind jedoch auch nicht besonders sicher. Sie sind über sichtbar
docker inspect
und stehen daher jedem Benutzer zur Verfügung, derdocker
Befehle ausführen kann. (Natürlich hat jeder Benutzer, derdocker
auf dem Host Zugriff hat, sowieso auch root .)Mein bevorzugtes Muster ist die Verwendung eines Wrapper-Skripts als
ENTRYPOINT
oderCMD
. Das Wrapper-Skript kann zur Laufzeit zuerst Geheimnisse von einem externen Speicherort in den Container importieren und dann die Anwendung ausführen und die Geheimnisse bereitstellen. Die genaue Mechanik hängt von Ihrer Laufzeitumgebung ab. In AWS können Sie eine Kombination aus IAM-Rollen, dem Key Management Service und S3 verwenden, um verschlüsselte Geheimnisse in einem S3-Bucket zu speichern. Etwas wie HashiCorp Vault oder Credstash ist eine weitere Option.AFAIK Es gibt kein optimales Muster für die Verwendung vertraulicher Daten als Teil des Erstellungsprozesses. Tatsächlich habe ich eine SO-Frage zu diesem Thema. Sie können Docker-Squash verwenden , um Ebenen aus einem Bild zu entfernen. Zu diesem Zweck gibt es in Docker jedoch keine native Funktionalität.
Möglicherweise finden Sie Shykes- Kommentare zur Konfiguration in Containern hilfreich.
quelle
.config
Dateien enthalten .docker inspect
.docker inspect
. Wenn der Angreifer bereits sudo kann, ist es wahrscheinlich ziemlich niedrig auf Ihrer Liste der Dinge, die jetzt schief gehen können, Ihr Passwort aus Docker Inspect zu entreißen. Dieses besondere Detail scheint mir ein akzeptables Risiko zu sein.Unser Team vermeidet es, Anmeldeinformationen in Repositorys zu speichern, sodass sie nicht zugelassen werden
Dockerfile
. Unsere beste Vorgehensweise bei Anwendungen ist die Verwendung von Creds aus Umgebungsvariablen.Wir lösen dies mit
docker-compose
.Innerhalb
docker-compose.yml
können Sie eine Datei angeben, die die Umgebungsvariablen für den Container enthält:Stellen Sie sicher , hinzufügen
.env
zu.gitignore
, dann die Anmeldeinformationen innerhalb der eingestellten.env
Datei wie:Speichern Sie die
.env
Datei lokal oder an einem sicheren Ort, an dem der Rest des Teams sie abrufen kann.Siehe: https://docs.docker.com/compose/environment-variables/#/the-env-file
quelle
.gitignore
damit die.env
Datei mit vertraulichen Informationen nicht in GitHub eingecheckt wird. Ich bin mir ziemlich sicher, dass dies nicht funktioniert, wenn Sie es hinzufügen.dockerignore
.env
Datei nicht einchecke und eine Bereitstellung auf einem Server vor Ort durchführe, schlagen Sie vor, die.env
Datei manuell erneut auf dem Server zu erstellen ?Docker jetzt (Version 1.13 oder 17.06 und höher) unterstützt die Verwaltung geheimer Informationen. Hier ist eine Übersicht und eine detailliertere Dokumentation
Eine ähnliche Funktion gibt es in Kubernetes und DCOS
quelle
docker secret create
:: Geheimnis erstellendocker secret inspect
: Detaillierte Informationen zu einem Geheimnis anzeigendocker secret ls
: Alle Geheimnisse anzeigendocker secret rm
: Ein bestimmtes geheimes--secret
Flag entfernen fürdocker service create
: Ein Geheimnis während der Diensterstellung erstellen--secret-add
und--secret-rm
Flags fürdocker service update
: Den Wert eines Geheimnisses aktualisieren oder ein Geheimnis entfernen während der Service-Update-Aufgabe. Docker-Geheimnisse werden in Ruhe auf Manager-Knoten geschützt und beim Starten des Containers für Worker-Knoten bereitgestellt.Sie sollten einem Container niemals Anmeldeinformationen hinzufügen, es sei denn, Sie senden die Creds an jeden, der das Bild herunterladen kann. Insbesondere ist dies und
ADD creds
späterRUN rm creds
nicht sicher, da die creds-Datei im endgültigen Image in einer Zwischenschicht des Dateisystems verbleibt. Jeder, der Zugriff auf das Bild hat, kann es einfach extrahieren.Die typische Lösung, die ich gesehen habe, wenn Sie Creds zum Auschecken von Abhängigkeiten benötigen, besteht darin, einen Container zum Erstellen eines anderen zu verwenden. Das heißt, normalerweise befindet sich in Ihrem Basiscontainer eine Build-Umgebung, die Sie aufrufen müssen, um Ihren App-Container zu erstellen. Die einfache Lösung besteht also darin, Ihre App-Quelle und dann
RUN
die Build-Befehle hinzuzufügen . Dies ist unsicher, wenn Sie Creds benötigenRUN
. Stattdessen legen Sie Ihre Quelle in einem lokalen Verzeichnis ab. Führen Siedocker run
den Container (wie in ) aus, um den Erstellungsschritt auszuführen, wobei das lokale Quellverzeichnis als Volume bereitgestellt und die Creds entweder injiziert oder als anderes Volume bereitgestellt werden. Sobald der Erstellungsschritt abgeschlossen ist, erstellen Sie Ihren endgültigen Container, indem Sie einfachADD
das lokale Quellverzeichnis aufrufen, das jetzt die erstellten Artefakte enthält.Ich hoffe, Docker fügt einige Funktionen hinzu, um dies alles zu vereinfachen!
Update: Es sieht so aus, als ob die Methode in Zukunft verschachtelte Builds haben wird. Kurz gesagt, die Docker-Datei würde einen ersten Container beschreiben, der zum Erstellen der Laufzeitumgebung verwendet wird, und dann einen zweiten verschachtelten Container-Build, der alle Teile zum endgültigen Container zusammenfügen kann. Auf diese Weise befindet sich das Build-Time-Material nicht im zweiten Container. Dies ist eine Java-App, bei der Sie das JDK zum Erstellen der App benötigen, aber nur die JRE zum Ausführen. Es werden eine Reihe von Vorschlägen diskutiert. Beginnen Sie am besten unter https://github.com/docker/docker/issues/7115 und folgen Sie einigen Links für alternative Vorschläge.
quelle
Eine Alternative zur Verwendung von Umgebungsvariablen, die bei vielen von ihnen unübersichtlich werden können, besteht darin, Volumes zu verwenden, um ein Verzeichnis auf dem Host im Container zugänglich zu machen.
Wenn Sie alle Ihre Anmeldeinformationen als Dateien in diesem Ordner ablegen, kann der Container die Dateien lesen und nach Belieben verwenden.
Beispielsweise:
Viele Programme können ihre Anmeldeinformationen aus einer separaten Datei lesen. Auf diese Weise können Sie das Programm einfach auf eine der Dateien verweisen.
quelle
Nur zur Laufzeit Lösung
Docker-Compose bietet auch eine Lösung ohne Schwarmmodus (seit Version 1.11: Geheimnisse mit Bind-Mounts ).
Die Geheimnisse werden
/run/secrets/
von Docker-Compose als Dateien unten gemountet . Dies löst das Problem zur Laufzeit (Ausführen des Containers), jedoch nicht zur Build-Zeit (Erstellen des Images), da/run/secrets/
es nicht zur Build-Zeit bereitgestellt wird. Darüber hinaus hängt dieses Verhalten davon ab, ob der Container mit Docker-Compose ausgeführt wird.Beispiel:
Dockerfile
docker-compose.yml
Führen Sie zum Erstellen Folgendes aus:
Weiterführende Literatur:
quelle
Mit Docker v1.9 können Sie die ARG-Anweisung verwenden , um Argumente abzurufen, die bei der Build-Aktion über die Befehlszeile an das Image übergeben wurden . Verwenden Sie einfach das Flag --build-arg . So können Sie vermeiden, explizite Passwörter (oder andere sinnvolle Informationen) in der Docker-Datei zu speichern und diese im laufenden Betrieb weiterzugeben.
Quelle: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg
Beispiel:
Dockerfile
Befehl image erstellen
während des Builds drucken
Ich hoffe es hilft! Tschüss.
quelle
--build-arg var=secret
Übergabe eines privaten SSH-Schlüssels an ein Image nicht empfiehlt , ist keine Begründung dokumentiert. Kann es jemand erklären?docker history
Exposuresbuild-arg
/ARG
Variablen verfügbar sind. Man kann jedes Bild ziehen, es untersuchen und alle Geheimnisse sehen, die während des Builds alsbuild-arg
/ARG
-Parameter übergeben wurden.Mein Ansatz scheint zu funktionieren, ist aber wahrscheinlich naiv. Sag mir, warum es falsch ist.
ARGs, die während der Docker-Erstellung festgelegt wurden, werden durch den Unterbefehl "Verlauf" verfügbar gemacht. Wenn Sie einen Container ausführen, stehen dem Container die im Befehl run angegebenen Umgebungsvariablen zur Verfügung, sind jedoch nicht Teil des Abbilds.
Führen Sie in der Docker-Datei ein Setup durch, das keine geheimen Daten enthält. Stellen Sie eine CMD von so etwas wie ein
/root/finish.sh
. Verwenden Sie im Befehl run Umgebungsvariablen, um geheime Daten in den Container zu senden.finish.sh
Verwendet die Variablen im Wesentlichen, um Build-Aufgaben abzuschließen.Um die Verwaltung der geheimen Daten zu vereinfachen, legen Sie sie in einer Datei ab, die vom Docker geladen wird, der mit dem
--env-file
Switch ausgeführt wird. Halten Sie die Datei natürlich geheim..gitignore
und derartige.Läuft für mich
finish.sh
ein Python-Programm. Es prüft, ob es noch nicht ausgeführt wurde, und beendet dann das Setup (z. B. kopiert es den Datenbanknamen in Djangossettings.py
).quelle
Es gibt einen neuen Docker- Befehl für die Verwaltung von "Geheimnissen". Das funktioniert aber nur für Schwarmcluster.
quelle
Die 12-Faktor-App-Methodik besagt, dass jede Konfiguration in Umgebungsvariablen gespeichert werden sollte.
Docker Compose kann in der Konfiguration Variablen ersetzen , sodass Kennwörter vom Host an den Docker übergeben werden können.
quelle
Obwohl ich völlig einverstanden bin, gibt es keine einfache Lösung. Es gibt weiterhin einen einzigen Fehlerpunkt. Entweder die Docker-Datei usw. usw. Apcera hat einen Plan, der wie ein Kumpel aussieht - doppelte Authentifizierung. Mit anderen Worten, zwei Container können nur dann kommunizieren, wenn eine Apcera-Konfigurationsregel vorhanden ist. In ihrer Demo war die UID / PWD im Klartext und konnte nicht wiederverwendet werden, bis der Administrator die Verknüpfung konfiguriert hatte. Damit dies funktioniert, bedeutete es wahrscheinlich, dass Docker oder zumindest das Netzwerk-Plugin gepatcht wurde (falls es so etwas gibt).
quelle