Sichere Geheimnisse beim Erstellen von Docker Compose

Vor Beginn des Python Web Developer- Kurses wurde eine Übersetzung des Artikels erstellt .




Wenn Sie ein Docker-Image erstellen, benötigen Sie möglicherweise Geheimnisse, z. B. ein Kennwort für ein privates Paket-Repository. Sie möchten nicht, dass dieses Geheimnis im Image landet, da dann jeder, der Zugriff auf das Image erhält, Zugriff auf Ihr privates Repository erhält.
Hinweis : Wenn Sie denken, warum nicht einfach Umgebungsvariablen verwenden? Welche werden zur Laufzeit beim Erstellen eines Bildes für Geheimnisse verwendet? Dieser Artikel konzentriert sich auf Build-Geheimnisse, die beim Erstellen eines Images mithilfe einer Docker-Datei verwendet werden.
Neuere Versionen von Docker verwalten Geheimnisse mithilfe des experimentellen BuildKit- Dienstes . In Docker Compose 1.25 und höher können Sie bereits Bilder mit BuildKit erstellen. Leider befindet sich die Fähigkeit, sicher mit Geheimnissen von Compose zu arbeiten, ab März 2020 noch in der Entwicklung .

Was ist jetzt zu tun?

Im heutigen Artikel werde ich zeigen, wie Sie dieselbe Docker-Datei verwenden können, um sicher Geheimnisse zu schaffen, aber die Vorteile einer schnellen Entwicklung mit Docker Compose nicht verpassen.

Zwei Optionen für die Verwendung Ihrer Docker-Datei


Es ist sehr praktisch, dasselbe Dockerfile für die Produktion und für die lokale Entwicklung mit Docker Compose zu verwenden. Normalerweise verwenden Sie die Docker-Datei zusammen mit der Build-Funktion von Compose:

version: "3.7"
services:
  yourapp:
    build:
      context: "."	

Dann können Sie tun:

$ docker-compose up

Mit diesem Befehl können Sie das Image (neu) zusammenstellen und dann ausführen.
Zur Verwendung in der Produktion sammeln Sie das Bild und senden es mit Push :

$ docker build -t myimage .
$ docker push myimage

Und während alles gut läuft. Aber was ist, wenn Sie einen geheimen Build benötigen?

Erster Versuch (unsicher)


Angenommen, Sie haben ein Skript, das einen geheimen Build benötigt, um beispielsweise ein Python-Paket aus einem privaten DevPI- Repository herunterzuladen . Der Einfachheit halber werden wir das Geheimnis einfach mit Hilfe ableiten, um use-secret.shzu zeigen, dass wir es haben.

#!/bin/bash
set -euo pipefail

echo "Secret is: $THEPASSWORD"

Sie können das Geheimnis einfach mithilfe der Docker-Build-Argumente weitergeben, da diese überall unterstützt werden, auch in Docker Compose.
Hinweis : Über den Rahmen unserer Diskussion hinaus möchte ich sagen, dass die Verwendung von Docker-Dateien in diesem Artikel nicht die beste Vorgehensweise ist. Eine übermäßige Komplexität kann jedoch die Vermittlung der Hauptbedeutung des Artikels beeinträchtigen.
Wenn Sie Ihre Python-Anwendung in der Produktion mit Docker ausführen möchten, gibt es zwei Möglichkeiten, dies zu tun:


FROM python:3.8-slim-buster
# Using ARG for build secrets is INSECURE!
ARG THEPASSWORD
COPY use_secret.sh .
RUN ./use_secret.sh

Wir können schreiben docker-compose.yml, was im Geheimen übermittelt wird:

version: "3.7"
services:
  yourapp:
    build:
      context: "."
      args:
        THEPASSWORD: "s3kr!t"

Für lokale Arbeiten können Sie ein Image mit Compose ausführen oder erstellen:

$ docker-compose build | grep Secret
Secret is: s3kr!t

Und alles ist gut.

Wir können das Image auch mit Docker zusammenstellen, um es in die Image-Registrierung zu verschieben:

$ docker build -t myimage --build-arg THEPASSWORD=s3krit . | grep Secret
Secret is: s3krit

Dies zu tun ist unsicher: Mach es niemals . Wenn wir uns entscheiden, die Ebenen des Bildes zu betrachten, werden wir das Geheimnis darin sehen!

$ docker history myimage
IMAGE               CREATED              CREATED BY                                      SIZE
c224231ec30b        47 seconds ago       |1 THEPASSWORD=s3krit /bin/sh -c ./use_secre…   0B
6aef62acf0db        48 seconds ago       /bin/sh -c #(nop) COPY file:7aa28bbe6595e0d5…   62B
f88b19ca8e65        About a minute ago   /bin/sh -c #(nop)  ARG THEPASSWORD              0B
...

Jeder, der Zugriff auf dieses Bild erhält, erkennt Ihr Passwort. Was kann man dann tun?

BuildKit-Geheimnisse (Teillösung)


BuildKit ist eine neue (und noch experimentelle) Lösung zum Erstellen von Docker-Images, die unter anderem die sichere Verwendung von Geheimnissen während der Montage unterstützt . Docker Compose unterstützt BuildKit seit Version 1.25.

Es gibt jedoch ein Problem: Docker Compose unterstützt die BuildKit-Geheimfunktionen immer noch nicht. Derzeit wird daran gearbeitet , aber ab März 2020 gibt es keine vorgefertigten Lösungen, ganz zu schweigen von einer stabilen Version.

Daher werden wir diese beiden Ansätze kombinieren:

  • Docker Compose verwendet weiterhin Build-Argumente, um Geheimnisse weiterzugeben.
  • Für ein Produktions-Image, das mit Docker Build erstellt wurde, verwenden wir BuildKit, um Geheimnisse weiterzugeben.

Auf diese Weise können wir dieselbe Docker-Datei verwenden, um lokal und in der Produktion zu arbeiten.
BuildKit arbeitet mit Geheimnissen wie folgt: Die Datei mit Geheimnissen wird in einem temporären Verzeichnis bereitgestellt, während der RUN-Befehl ausgeführt wird, z /var/secrets/thepassword. Da es während der Ausführung des RUN-Befehls bereitgestellt wird, wird es nicht zum endgültigen Image hinzugefügt.

Wir werden die Datei ändern use_secret.sh, um zu überprüfen, ob eine solche temporäre Datei vorhanden ist. Wenn vorhanden, werden die Einstellungen der Umgebungsvariablen verwendet $THEPASSWORD. Wenn die Datei nicht vorhanden ist, kehren wir zur Umgebungsvariablen zurück. Das heißt, es $THEPASSWORDkann mit BuildKit oder Build-Argumenten installiert werden:

#!/bin/bash
set -euo pipefail
if [ -f /run/secrets/thepassword ]; then
   export THEPASSWORD=$(cat /run/secrets/thepassword)
fi

echo "Secret is: $THEPASSWORD"

Dann werden wir die Docker-Datei ändern, um das BuildKit hinzuzufügen und das Geheimnis zu mounten:

# syntax = docker/dockerfile:1.0-experimental
FROM python:3.8-slim-buster
# Only use the build arg for local development:
ARG THEPASSWORD
COPY use_secret.sh .
# Mount the secret to /run/secrets:
RUN --mount=type=secret,id=thepassword ./use_secret.sh

docker-compose.ymlWir ändern die Datei nicht :

version: "3.7"
services:
  yourapp:
    build:
      context: "."
      args:
        THEPASSWORD: "s3kr!t"

Jetzt müssen Sie zwei Umgebungsvariablen definieren, von denen eine Docker mitteilt, dass Sie BuildKit verwenden müssen, die zweite, dass Compose die CLI-Version von Docker und daher BuildKit verwenden muss. Wir werden auch das Geheimnis in die Datei schreiben:

$ export DOCKER_BUILDKIT=1
$ export COMPOSE_DOCKER_CLI_BUILD=1
$ echo 's3krit' > /tmp/mypassword

Bei Compose verwenden wir die Build-Argumente:

$ docker-compose build --progress=plain \
    --no-cache 2>&1 | grep Secret
#12 0.347 Secret is: s3kr!t

Bitte beachten Sie, dass Sie --no-cacheverstehen müssen, dass das Image wirklich neu erstellt wird, wenn Sie alle oben genannten Schritte selbst ausführen. Im wirklichen Leben kann dieser Parameter weggelassen werden. 2>&1Weiterleiten stderran stdoutfür korrekten Betrieb grep.

Wenn wir bereit sind, auf der Produktion aufzubauen, verwenden wir Docker Build mit der Funktionalität von Geheimnissen aus BuildKit:

$ docker build --no-cache -t myimage \
    --secret id=thepassword,src=/tmp/mypassword \
    --progress=plain . 2>&1 | grep Secret
#12 0.359 Secret is: s3krit

Ist es sicher?


Stellen wir sicher, dass das Geheimnis nicht sichtbar ist:

$ docker history myimage
IMAGE               CREATED             CREATED BY                                      SIZE
a77f3c32b723        25 seconds ago      RUN |1 THEPASSWORD= /bin/sh -c ./use_secret.…   0B
<missing>           25 seconds ago      COPY use_secret.sh . # buildkit                 160B
...

Hurra! Wir haben das Geheimnis mit Compose und an dieselbe Docker-Datei weitergegeben docker buildund im letzteren Fall das Geheimnis der Versammlung nicht preisgegeben .



Erfahren Sie mehr über den Kurs.



All Articles