Docker
Dockerfiles
Suche…
Einführung
Dockerfiles sind Dateien, mit denen Docker-Images programmatisch erstellt werden. Sie ermöglichen es Ihnen, schnell und reproduzierbar ein Docker-Image zu erstellen und sind daher für die Zusammenarbeit hilfreich. Docker-Dateien enthalten Anweisungen zum Erstellen eines Docker-Images. Jede Anweisung ist in einer Zeile geschrieben und in der Form <INSTRUCTION><argument(s)>
. Docker-Dateien werden verwendet, um Docker-Images mit dem docker build
Befehl zu docker build
.
Bemerkungen
Dockerfiles haben die Form:
# This is a comment
INSTRUCTION arguments
- Kommentare beginnen mit einem
#
- Anweisungen sind nur in Großbuchstaben
- Die erste Anweisung einer Docker-Datei muss
FROM
, um das Basisabbild anzugeben
Beim Erstellen einer Docker-Datei sendet der Docker-Client einen "Build-Kontext" an den Docker-Daemon. Der Build-Kontext enthält alle Dateien und Ordner im selben Verzeichnis wie die Docker-Datei. COPY
und ADD
Vorgänge können nur Dateien aus diesem Kontext verwenden.
Einige Docker-Dateien beginnen mit:
# escape=`
Hiermit wird der Docker-Parser angewiesen, `
als Escape-Zeichen anstelle von \
. Dies ist vor allem für Windows Docker-Dateien nützlich.
HelloWorld Dockerfile
Eine minimale Docker-Datei sieht folgendermaßen aus:
FROM alpine
CMD ["echo", "Hello StackOverflow!"]
Dadurch wird Docker angewiesen, ein Abbild auf der Grundlage von Alpine ( FROM
), einer minimalen Verteilung für Container, zu erstellen und beim Ausführen des resultierenden Abbilds einen bestimmten Befehl ( CMD
) auszuführen.
Bauen Sie es auf und führen Sie es aus:
docker build -t hello .
docker run --rm hello
Dies wird ausgegeben:
Hello StackOverflow!
Dateien kopieren
Verwenden Sie zum Kopieren von Dateien aus dem Build-Kontext in einem Docker-Image die COPY
Anweisung:
COPY localfile.txt containerfile.txt
Wenn der Dateiname Leerzeichen enthält, verwenden Sie die alternative Syntax:
COPY ["local file", "container file"]
Der Befehl COPY
unterstützt Platzhalter. Es kann beispielsweise verwendet werden, um alle Bilder in das Verzeichnis images/
zu kopieren:
COPY *.jpg images/
Hinweis: In diesem Beispiel sind möglicherweise keine images/
vorhanden. In diesem Fall erstellt Docker es automatisch.
Einen Hafen freigeben
Um deklarierte Ports aus einer Dockerfile zu deklarieren, verwenden Sie die Anweisung EXPOSE
:
EXPOSE 8080 8082
Die Einstellung der freigelegten Ports kann von der Docker-Befehlszeile aus überschrieben werden. Es ist jedoch empfehlenswert, sie explizit in der Docker-Datei festzulegen, da dies die Funktionsweise einer Anwendung erleichtert.
Dockerfiles beste Praktiken
Gemeinsame Operationen gruppieren
Docker erstellt Bilder als eine Sammlung von Ebenen. Jede Ebene kann nur Daten hinzufügen, selbst wenn diese Daten anzeigen, dass eine Datei gelöscht wurde. Jede Anweisung erstellt eine neue Ebene. Zum Beispiel:
RUN apt-get -qq update
RUN apt-get -qq install some-package
Hat ein paar Nachteile:
- Es werden zwei Ebenen erstellt, wodurch ein größeres Bild erzeugt wird.
- Die alleinige Verwendung von
apt-get update
in einerRUN
Anweisung führt zu Zwischenspeicherungsproblemen und anschließend könnenapt-get install
fehlschlagen . Angenommen, Sie ändernapt-get install
durch Hinzufügen zusätzlicher Pakete. Dann interpretiert das Andockfenster die ursprünglichen und geänderten Anweisungen als identisch und verwendet den Cache von den vorherigen Schritten. Daher wird der Befehlapt-get update
nicht ausgeführt, da seine zwischengespeicherte Version während des Builds verwendet wird.
Verwenden Sie stattdessen:
RUN apt-get -qq update && \
apt-get -qq install some-package
da dies nur eine Schicht erzeugt.
Erwähnen Sie den Betreuer
Dies ist normalerweise die zweite Zeile der Dockerfile. Es sagt, wer verantwortlich ist und helfen kann.
LABEL maintainer John Doe <[email protected]>
Wenn Sie es überspringen, wird Ihr Bild nicht beschädigt. Aber es hilft auch nicht Ihren Benutzern.
Sei präzise
Halten Sie Ihre Dockerfile kurz. Wenn ein komplexes Setup erforderlich ist, sollten Sie ein dediziertes Skript verwenden oder Basisabbilder einrichten.
USER-Anweisung
USER daemon
Der USER
- Befehl setzt die Benutzername oder UID zu verwenden , wenn das Bild ausgeführt wird und für jeden RUN
, CMD
und ENTRYPOINT
Anweisungen , die es in dem folgen Dockerfile
.
WORKDIR-Anweisung
WORKDIR /path/to/workdir
Die WORKDIR
Anweisung legt das Arbeitsverzeichnis für alle Anweisungen RUN
, CMD
, ENTRYPOINT
, COPY
und ADD
, die in der Docker-Datei folgen. Wenn das WORKDIR
nicht existiert, wird es erstellt, auch wenn es nicht in einer nachfolgenden Dockerfile
Anweisung verwendet wird.
Es kann mehrmals in einer Dockerfile
. Wenn ein relativer Pfad angegeben wird, ist dieser relativ zum Pfad der vorherigen WORKDIR
Anweisung. Zum Beispiel:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Die Ausgabe des letzten pwd
Befehls in dieser Dockerfile
wäre /a/b/c
.
Die WORKDIR
Anweisung kann Umgebungsvariablen auflösen, die zuvor mit ENV
. Sie können nur Umgebungsvariablen verwenden, die explizit in der Dockerfile
. Zum Beispiel:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
Die Ausgabe des letzten pwd
Befehls in dieser Docker-Datei wäre /path/$DIRNAME
VOLUME-Anweisung
VOLUME ["/data"]
Mit der Anweisung VOLUME
wird ein Mountpunkt mit dem angegebenen Namen erstellt und als für extern gemountete Volumes auf dem nativen Host oder anderen Containern markiert. Der Wert kann ein JSON-Array, VOLUME ["/var/log/"]
oder eine einfache Zeichenfolge mit mehreren Argumenten sein, beispielsweise VOLUME /var/log
oder VOLUME /var/log /var/db
. Weitere Informationen / Beispiele und Installationsanweisungen über den Docker-Client finden Sie in der Dokumentation zum Freigeben von Verzeichnissen über Volumes.
Der docker run
Befehl initialisiert den neu erstellten Datenträger mit allen Daten, die an der angegebenen Position im Basisabbild vorhanden sind. Betrachten Sie beispielsweise das folgende Dockerfile-Snippet:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
Diese Docker-Datei führt zu einem Bild, das das Andockfenster veranlasst, einen neuen Mount-Punkt unter / myvol zu erstellen und die Begrüßungsdatei in das neu erstellte Volume zu kopieren.
Hinweis: Wenn Build-Schritte die Daten innerhalb des Volumes ändern, nachdem sie deklariert wurden, werden diese Änderungen verworfen.
Anmerkung: Die Liste wird als JSON-Array analysiert. Das bedeutet, dass Sie doppelte Anführungszeichen (“) für Wörter verwenden müssen, nicht einfache Anführungszeichen (').
COPY-Anweisung
COPY
hat zwei Formen:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"] (this form is required for paths containing whitespace)
Die COPY
Anweisung kopiert neue Dateien oder Verzeichnisse aus <src>
und fügt sie dem Dateisystem des Containers unter dem Pfad <dest>
.
Es können mehrere <src>
-Ressourcen angegeben werden, sie müssen jedoch relativ zu dem Quellverzeichnis sein, das erstellt wird (dem Kontext des Builds).
Jedes <src>
kann Platzhalter enthalten, und der Abgleich wird mit den filepath.Match
Regeln von Go filepath.Match
. Zum Beispiel:
COPY hom* /mydir/ # adds all files starting with "hom"
COPY hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
Der <dest>
ist ein absoluter Pfad oder ein Pfad relativ zu WORKDIR
, in den die Quelle in den WORKDIR
kopiert wird.
COPY test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
COPY test /absoluteDir/ # adds "test" to /absoluteDir/
Alle neuen Dateien und Verzeichnisse werden mit einer UID und einer GID von 0 erstellt.
Hinweis: Wenn Sie mit stdin ( docker build - < somefile
) docker build - < somefile
, gibt es keinen Build-Kontext, sodass COPY
nicht verwendet werden kann.
COPY
beachtet die folgenden Regeln:
Der Pfad
<src>
muss sich im Kontext des Builds befinden. Sie können nichtCOPY
../something / etwas, weil der erste Schritt eines Docker Build ist das Kontext Verzeichnis (und Unterverzeichnisse) mit der Docker - Daemon zu senden.Wenn
<src>
ein Verzeichnis ist, wird der gesamte Inhalt des Verzeichnisses einschließlich der Metadaten des Dateisystems kopiert. Hinweis: Das Verzeichnis selbst wird nicht kopiert, sondern nur der Inhalt.Wenn
<src>
eine andere Art von Datei ist, wird sie zusammen mit ihren Metadaten einzeln kopiert. Wenn in diesem Fall<dest>
mit einem nachgestellten Schrägstrich / endet, wird dies als Verzeichnis betrachtet und der Inhalt von<src>
wird in<dest>/base(<src>)
.Wenn mehrere
<src>
-Ressourcen angegeben werden, entweder direkt oder aufgrund der Verwendung eines Platzhalters, muss<dest>
ein Verzeichnis sein und mit einem Schrägstrich/
enden.Wenn
<dest>
nicht mit einem nachgestellten Schrägstrich endet, wird dies als reguläre Datei betrachtet und der Inhalt von<src>
wird an<dest>
.Wenn
<dest>
nicht vorhanden ist, wird es zusammen mit allen fehlenden Verzeichnissen in seinem Pfad erstellt.
Die ENV- und ARG-Anweisung
ENV
ENV <key> <value>
ENV <key>=<value> ...
Die Anweisung ENV
setzt die Umgebungsvariable <key>
auf den Wert. Dieser Wert befindet sich in der Umgebung aller "nachkommenden" Dockerfile-Befehle und kann auch in vielen Inline-Versionen ersetzt werden.
Die ENV
Anweisung hat zwei Formen. Die erste Form ENV <key> <value>
setzt eine einzelne Variable auf einen Wert. Die gesamte Zeichenfolge nach dem ersten Leerzeichen wird als <value>
behandelt, einschließlich Zeichen wie Leerzeichen und Anführungszeichen.
Die zweite Form ENV <key>=<value> ...
ermöglicht das gleichzeitige Setzen mehrerer Variablen. Beachten Sie, dass das zweite Formular das Gleichheitszeichen (=) in der Syntax verwendet, das erste Formular jedoch nicht. Wie bei der Befehlszeilenanalyse können Anführungszeichen und umgekehrte Schrägstriche verwendet werden, um Leerzeichen in Werte einzuschließen.
Zum Beispiel:
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
und
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
führt im endgültigen Container zu den gleichen Nettoergebnissen, aber die erste Form wird bevorzugt, da sie eine einzelne Cache-Ebene erzeugt.
Die mit ENV
festgelegten Umgebungsvariablen bleiben erhalten, wenn ein Container vom resultierenden Image aus ausgeführt wird. Sie können die Werte mithilfe der Docker- docker run --env <key>=<value>
und mithilfe des docker run --env <key>=<value>
.
ARG
Wenn Sie die Einstellung nicht beibehalten möchten, verwenden Sie stattdessen ARG
. ARG
setzt Umgebungen nur während des Builds. Zum Beispiel Einstellung
ENV DEBIAN_FRONTEND noninteractive
apt-get
Benutzer können auf einem Debian-basierten Image verwirrt werden, wenn sie den Container in einem interaktiven Kontext über das docker exec -it the-container bash
eingeben.
Verwenden Sie stattdessen:
ARG DEBIAN_FRONTEND noninteractive
Sie können alternativ auch einen Wert für einen einzelnen Befehl festlegen, indem Sie Folgendes verwenden:
RUN <key>=<value> <command>
EXPOSE Anweisung
EXPOSE <port> [<port>...]
Die Anweisung EXPOSE
informiert Docker darüber, dass der Container zur Laufzeit die angegebenen Netzwerkports abhört. EXPOSE
macht die Ports des Containers NICHT für den Host zugänglich. Dazu müssen Sie entweder das -p
Flag zum Veröffentlichen eines -P
oder das -P
Flag zum Veröffentlichen aller freigelegten Ports verwenden. Diese Flags werden im docker run [OPTIONS] IMAGE [COMMAND][ARG...]
, um den Port für den Host docker run [OPTIONS] IMAGE [COMMAND][ARG...]
. Sie können eine Portnummer freigeben und extern unter einer anderen Nummer veröffentlichen.
docker run -p 2500:80 <image name>
Dieser Befehl erstellt einen Container mit dem Namen <image> und bindet den Port 80 des Containers an den Port 2500 der Hostmaschine.
Informationen zum Einrichten der Portumleitung auf dem Hostsystem finden Sie unter Verwenden des Kennzeichens -P
. Die Docker-Netzwerkfunktion unterstützt das Erstellen von Netzwerken, ohne dass Ports innerhalb des Netzwerks verfügbar gemacht werden müssen (detaillierte Informationen finden Sie in der Übersicht dieser Funktion).
LABEL-Anweisung
LABEL <key>=<value> <key>=<value> <key>=<value> ...
Die LABEL
Anweisung fügt einem Bild Metadaten hinzu. Ein LABEL
ist ein Schlüssel-Wert-Paar. Verwenden Sie zum LABEL
von Leerzeichen in einen LABEL
Wert Anführungszeichen und LABEL
Schrägstriche wie bei der Befehlszeilenanalyse. Einige Anwendungsbeispiele:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
Ein Bild kann mehr als ein Label haben. Um mehrere Labels anzugeben, empfiehlt Docker, die Labels möglichst in einer einzigen LABEL
Anweisung zu kombinieren. Jede LABEL
Anweisung erzeugt eine neue Ebene, die zu einem ineffizienten Bild führen kann, wenn Sie viele Beschriftungen verwenden. Dieses Beispiel ergibt eine einzelne Bildebene.
LABEL multi.label1="value1" multi.label2="value2" other="value3"
Das oben Gesagte kann auch geschrieben werden als:
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
Labels sind additiv, einschließlich LABEL
in FROM
Bildern. Wenn Docker auf ein bereits vorhandenes Label / einen Schlüssel stößt, überschreibt der neue Wert alle vorherigen Labels mit identischen Schlüsseln.
Verwenden Sie den Andockbefehl, um die Beschriftungen eines Bildes anzuzeigen.
"Labels": {
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},
CMD-Anweisung
Die CMD
Anweisung hat drei Formen:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
Es kann nur eine CMD
Anweisung in einer Dockerfile
. Wenn Sie mehr als eine CMD
CMD
wird nur die letzte CMD
wirksam.
Der Hauptzweck einer CMD
besteht darin, Standardwerte für einen ausgeführten Container bereitzustellen. Diese Standardwerte können eine ausführbare Datei enthalten oder sie können die ausführbare Datei weglassen. In diesem Fall müssen Sie auch eine ENTRYPOINT
Anweisung angeben.
Anmerkung: Wenn CMD
verwendet wird, um Standardargumente für die Anweisung ENTRYPOINT
, sollten sowohl die Anweisungen CMD
als auch ENTRYPOINT
mit dem JSON-Array-Format angegeben werden.
Hinweis: Das exec-Formular wird als JSON-Array analysiert. Das bedeutet, dass Sie doppelte Anführungszeichen (“) für Wörter verwenden müssen, nicht einfache Anführungszeichen (').
Hinweis: Im Gegensatz zum Shell-Formular ruft das Exec-Formular keine Befehls-Shell auf. Dies bedeutet, dass eine normale Shell-Verarbeitung nicht stattfindet. Beispielsweise führt CMD [ "echo", "$HOME" ]
keine Variablensubstitution bei $HOME
. Wenn Sie eine Shell-Verarbeitung wünschen, verwenden Sie entweder die Shell-Form oder führen Sie eine Shell direkt aus, zum Beispiel: CMD [ "sh", "-c", "echo $HOME" ]
.
Bei Verwendung in Shell- oder Exec-Formaten legt der CMD
Befehl fest, dass der Befehl ausgeführt wird, wenn das Image ausgeführt wird.
Wenn Sie die Shell-Form des CMD
, wird der Befehl in /bin/sh -c
:
FROM ubuntu
CMD echo "This is a test." | wc -
Wenn Sie Ihren Befehl ohne Shell ausführen möchten, müssen Sie den Befehl als JSON-Array ausdrücken und der ausführbaren Datei den vollständigen Pfad angeben. Diese Feldform ist das bevorzugte Format von CMD
. Alle zusätzlichen Parameter müssen einzeln als Strings im Array ausgedrückt werden:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
Wenn Sie möchten, dass Ihr Container jedes Mal dieselbe ausführbare Datei ENTRYPOINT
sollten Sie ENTRYPOINT
in Kombination mit CMD
in Betracht ENTRYPOINT
. Siehe ENTRYPOINT
.
Wenn der Benutzer Argumente für die Ausführung des Dockers angibt, überschreibt er den in CMD
angegebenen Standard.
Hinweis: Verwechseln Sie RUN
mit CMD
. RUN
tatsächlich einen Befehl zur Image-Erstellungszeit aus und überträgt das Ergebnis. CMD
führt zum Erstellungszeitpunkt nichts aus, gibt jedoch den beabsichtigten Befehl für das Image an.
MAINTAINER-Anweisung
MAINTAINER <name>
Mit der Anweisung MAINTAINER
können Sie das Autorenfeld der generierten Bilder festlegen.
DIE MAINTAINER-RICHTLINIE NICHT VERWENDEN
Gemäß der offiziellen Docker-Dokumentation ist die MAINTAINER
Anweisung veraltet. Stattdessen sollte man die LABEL
Anweisung verwenden, um den Autor der erzeugten Bilder zu definieren. Der LABEL
- Befehl ist flexibler, ermöglicht Metadaten Einstellung und können leicht mit dem Befehl betrachtet werden docker inspect
.
LABEL maintainer="[email protected]"
FROM Anweisung
FROM <image>
Oder
FROM <image>:<tag>
Oder
FROM <image>@<digest>
Die FROM
Anweisung legt das Basisbild für nachfolgende Anweisungen fest. Daher muss eine gültige Docker-Datei FROM
als erste Anweisung enthalten. Das Bild kann ein beliebiges gültiges Bild sein. Es ist besonders einfach, ein Bild aus den öffentlichen Repositorys zu ziehen.
FROM
muss die erste Anweisung ohne Kommentar in der Dockerfile sein.
FROM
kann in einer einzigen Docker-Datei mehrmals angezeigt werden, um mehrere Bilder zu erstellen. Notieren Sie sich vor jedem neuen FROM
Befehl einfach die letzte vom Commit ausgegebene Bild-ID.
Die Tag- oder Digest-Werte sind optional. Wenn Sie eine der beiden Optionen weglassen, geht der Builder standardmäßig von einer neuen Version aus. Der Builder gibt einen Fehler zurück, wenn er nicht mit dem Tag-Wert übereinstimmen kann.
RUN-Anweisung
RUN
hat 2 Formen:
RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN ["executable", "param1", "param2"] (exec form)
Die RUN
Anweisung führt alle Befehle in einer neuen Ebene über dem aktuellen Bild aus und schreibt die Ergebnisse fest. Das resultierende festgeschriebene Image wird für den nächsten Schritt in der Dockerfile
.
Das Beschichten von RUN
Anweisungen und das Generieren von Commits entspricht den Kernkonzepten von Docker, bei denen Commits billig sind und Container von jedem Punkt in der Historie eines Bildes erstellt werden können, ähnlich wie bei der Quellcodeverwaltung.
Die exec Form ermöglicht es , Shell String munging zu vermeiden und RUN
Befehle ein Basisbild verwenden , die nicht die angegebene ausführbare Shell enthält.
Die Standard-Shell für das Shell-Formular kann mit dem Befehl SHELL
geändert werden.
In der Shell-Form können Sie einen \
(Backslash) verwenden, um einen einzelnen RUN
Befehl in der nächsten Zeile fortzusetzen. Betrachten Sie zum Beispiel diese beiden Zeilen:
RUN /bin/bash -c 'source $HOME/.bashrc ;\
echo $HOME'
Zusammen entsprechen sie dieser einzelnen Zeile:
RUN /bin/bash -c 'source $HOME/.bashrc ; echo $HOME'
Hinweis: Wenn Sie eine andere Shell als '/ bin / sh' verwenden möchten, verwenden Sie das Exec-Formular, das in der gewünschten Shell übergeben wird. Zum Beispiel RUN ["/bin/bash", "-c", "echo hello"]
Hinweis: Das exec-Formular wird als JSON-Array analysiert. Das bedeutet, dass Sie doppelte Anführungszeichen ( “
) für Wörter verwenden müssen, nicht einfache Anführungszeichen ( '
).
Hinweis: Im Gegensatz zum Shell-Formular ruft das Exec-Formular keine Befehls-Shell auf. Dies bedeutet, dass eine normale Shell-Verarbeitung nicht stattfindet. Zum Beispiel führt RUN [ "echo", "$HOME" ]
keine Variablensubstitution bei $HOME
. Wenn Sie eine Shell-Verarbeitung wünschen, verwenden Sie entweder die Shell-Form oder führen Sie eine Shell direkt aus, zum Beispiel: RUN [ "sh", "-c", "echo $HOME" ]
.
Hinweis: Im JSON-Formular müssen umgekehrte Schrägstriche ausgeblendet werden. Dies ist insbesondere unter Windows relevant, wo der Backslash das Pfadtrennzeichen ist. Die folgende Zeile wird ansonsten als Shell-Form behandelt, da sie nicht gültig ist und unerwartet fehlschlägt: RUN ["c:\windows\system32\tasklist.exe"]
Die korrekte Syntax für dieses Beispiel lautet: RUN ["c:\\windows\\system32\\tasklist.exe"]
Der Cache für RUN
Anweisungen wird beim nächsten Build nicht automatisch ungültig gemacht. Der Cache für eine Anweisung wie RUN apt-get dist-upgrade -y
wird beim nächsten Build wiederverwendet. Der Cache für RUN
Anweisungen kann mit dem Flag --no-cache ungültig gemacht werden, z. B. Docker-Build --no-cache.
Weitere Informationen finden Sie im Handbuch Dockerfile Best Practices.
Der Cache für RUN
Anweisungen kann durch ADD
Anweisungen ungültig gemacht werden. Details finden Sie unten.
ONBUILD-Anweisung
ONBUILD [INSTRUCTION]
Der ONBUILD
Befehl fügt dem Bild einen Auslöserbefehl hinzu, der zu einem späteren Zeitpunkt ausgeführt wird, wenn das Bild als Basis für einen anderen Build verwendet wird. Der Trigger wird im Kontext des Downstream-Builds ausgeführt, als ob er unmittelbar nach dem FROM
Befehl in die Downstream-Docker-Datei eingefügt worden wäre.
Jede Build-Anweisung kann als Auslöser registriert werden.
Dies ist nützlich, wenn Sie ein Abbild erstellen, das als Basis zum Erstellen anderer Abbilder verwendet wird, z. B. eine Anwendungserstellungsumgebung oder einen Dämon, der mit einer benutzerspezifischen Konfiguration angepasst werden kann.
Wenn es sich bei Ihrem Image beispielsweise um einen wiederverwendbaren Python-Anwendungsersteller handelt, muss der Anwendungsquellcode in einem bestimmten Verzeichnis hinzugefügt werden. Möglicherweise muss danach ein Build-Skript aufgerufen werden. Sie können jetzt nicht einfach ADD
und RUN
aufrufen, da Sie noch keinen Zugriff auf den Anwendungsquellcode haben. Dieser wird für jeden Anwendungsaufbau unterschiedlich sein. Sie können Anwendungsentwickler einfach mit einer Boilerplate-Docker-Datei versehen, um sie in ihre Anwendung zu kopieren. Dies ist jedoch ineffizient, fehleranfällig und schwierig zu aktualisieren, da sie mit anwendungsspezifischem Code gemischt wird.
Die Lösung besteht darin, ONBUILD
zu verwenden, um erweiterte Anweisungen für die spätere Ausführung während der nächsten ONBUILD
zu registrieren.
So funktioniert das:
Wenn er auf eine ONBUILD
Anweisung ONBUILD
, fügt der Builder den Metadaten des zu ONBUILD
einen Auslöser hinzu. Die Anweisung wirkt sich sonst nicht auf den aktuellen Build aus.
Am Ende des Builds wird im Image-Manifest eine Liste aller Trigger unter dem Schlüssel OnBuild gespeichert. Sie können mit dem docker inspect
Befehl docker inspect
. Später kann das Image mit der FROM
Anweisung als Basis für einen neuen Build verwendet werden. Bei der Verarbeitung der FROM
Anweisung sucht der Downstream-Builder nach ONBUILD
Triggern und führt sie in der Reihenfolge aus, in der sie registriert wurden. Wenn einer der Trigger fehlschlägt, wird der FROM
Befehl abgebrochen, wodurch der Build fehlschlägt. Wenn alle Trigger erfolgreich sind, wird die FROM
Anweisung abgeschlossen und der Build wird wie gewohnt fortgesetzt.
Trigger werden nach ihrer Ausführung aus dem endgültigen Bild gelöscht. Mit anderen Worten, sie werden nicht von Enkelkindern vererbt.
Zum Beispiel könnten Sie so etwas hinzufügen:
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
Warnung: Das Verketten von ONBUILD
Anweisungen mit ONBUILD
ONBUILD
ist nicht zulässig.
Achtung: Die ONBUILD
Anweisung nicht auslösen können FROM
oder MAINTAINER
Anweisungen.
STOPSIGNAL-Anweisung
STOPSIGNAL signal
Die Anweisung STOPSIGNAL
setzt das Systemaufrufsignal, das an den Container gesendet wird, zum Beenden. Dieses Signal kann eine gültige vorzeichenlose Zahl sein, die mit einer Position in der Syscall-Tabelle des Kernels übereinstimmt, beispielsweise 9, oder ein Signalname im Format SIGNAME, beispielsweise SIGKILL.
HEALTHCHECK-Anweisung
Der HEALTHCHECK
Befehl hat zwei Formen:
HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
HEALTHCHECK NONE (disable any healthcheck inherited from the base image)
Die Anweisung HEALTHCHECK
teilt Docker mit, wie ein Container getestet werden kann, um zu überprüfen, ob er noch funktioniert. Dadurch können Fälle wie ein Webserver erkannt werden, der sich in einer Endlosschleife befindet und keine neuen Verbindungen verarbeiten kann, obwohl der Serverprozess noch ausgeführt wird.
Wenn für einen Container eine Integritätsprüfung angegeben wurde, hat er zusätzlich zum normalen Status einen Integritätsstatus. Dieser Status wird zunächst gestartet. Wenn eine Gesundheitsprüfung bestanden wird, wird sie gesund (in welchem Zustand sie zuvor war). Nach einer bestimmten Anzahl aufeinander folgender Fehler wird es ungesund.
Die Optionen, die vor CMD
werden können, sind:
--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--retries=N (default: 3)
Die Zustandsprüfung wird erst Sekunden nach dem Start des Containers ausgeführt und danach erneut Sekunden nach jeder vorherigen Prüfung.
Wenn ein einzelner Durchlauf der Prüfung länger dauert als Timeout-Sekunden, gilt die Prüfung als nicht bestanden.
Wiederholungen aufeinanderfolgender Fehler der Integritätsprüfung erfordern, dass der Container als fehlerhaft eingestuft wird.
Es kann nur eine HEALTHCHECK
Anweisung in einer Dockerfile
. Wenn Sie mehrere Listen HEALTHCHECK
wird nur der letzte HEALTHCHECK
wirksam.
Der Befehl nach dem CMD
Schlüsselwort kann entweder ein Shell-Befehl (z. B. HEALTHCHECK CMD /bin/check-running
) oder ein Exec-Array (wie bei anderen Dockerfile-Befehlen) sein (siehe ENTRYPOINT
für Details).
Der Beendigungsstatus des Befehls zeigt den Integritätsstatus des Containers an. Die möglichen Werte sind:
-
0: success
- der Behälter ist gesund und einsatzbereit -
1: unhealthy
- Der Container funktioniert nicht ordnungsgemäß -
2: starting
- Der Container ist noch nicht betriebsbereit, funktioniert aber ordnungsgemäß
Wenn die Sonde 2 zurückgibt ("Start"), wenn der Container bereits den Status "Start" verlassen hat, wird er stattdessen als "ungesund" behandelt.
Um beispielsweise alle fünf Minuten zu überprüfen, dass ein Webserver die Hauptseite der Website innerhalb von drei Sekunden bereitstellen kann:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
Um das Debuggen fehlgeschlagener Tests zu erleichtern, wird der von stdout oder stderr geschriebene Ausgabetext (UTF-8-codiert) im Integritätsstatus gespeichert und kann mit docker inspect
abgefragt werden. Diese Ausgabe sollte kurz gehalten werden (derzeit werden nur die ersten 4096 Bytes gespeichert).
Wenn sich der health_status
eines Containers ändert, wird ein health_status
Ereignis mit dem neuen Status generiert.
Die HEALTHCHECK
Funktion wurde in Docker 1.12 hinzugefügt.
SHELL-Anweisung
SHELL ["executable", "parameters"]
Mit der SHELL
Anweisung kann die Standard-Shell, die für die Shell-Form von Befehlen verwendet wird, überschrieben werden. Die Standardshell unter Linux ist ["/bin/sh", "-c"]
und unter Windows ["cmd", "/S", "/C"]
. Die SHELL
Anweisung muss in einer Dockerfile in JSON-Form geschrieben werden.
Die SHELL
Anweisung ist besonders nützlich unter Windows, wo es zwei häufig verwendete und recht unterschiedliche native Shells gibt: cmd und powershell sowie alternative Shells, einschließlich sh.
Die SHELL
Anweisung kann mehrmals erscheinen. Jede SHELL
Anweisung überschreibt alle vorherigen SHELL
Anweisungen und wirkt sich auf alle nachfolgenden Anweisungen aus. Zum Beispiel:
FROM windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
Die folgenden Anweisungen können von der SHELL
Anweisung beeinflusst werden, wenn ihre Shell-Form in einer Docker-Datei verwendet wird: RUN
, CMD
und ENTRYPOINT
.
Das folgende Beispiel ist ein allgemeines Muster unter Windows, das mit der SHELL
Anweisung optimiert werden kann:
...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
Der vom Docker aufgerufene Befehl lautet:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
Dies ist aus zwei Gründen ineffizient. Zunächst wird ein nicht notwendiger Befehlsprozessor cmd.exe (auch als Shell bezeichnet) aufgerufen. Zweitens erfordert jede RUN
Anweisung in der Shell-Form einen zusätzlichen Powershell-Befehl, der dem Befehl vorangestellt wird.
Um dies effizienter zu gestalten, kann einer von zwei Mechanismen eingesetzt werden. Verwenden Sie zum Beispiel die JSON-Form des RUN
Befehls, z.
...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
Das JSON-Formular ist zwar eindeutig und verwendet nicht die nicht benötigte cmd.exe, es erfordert jedoch mehr Ausführlichkeit durch doppelte Anführungszeichen und Escape-Anweisungen. Der alternative Mechanismus besteht darin, die SHELL
Anweisung und die Shell-Form zu verwenden, um eine natürlichere Syntax für Windows-Benutzer zu schaffen, insbesondere in Kombination mit der Escape-Parser-Direktive:
# escape=`
FROM windowsservercore
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
Ergebend:
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 3.584 kB
Step 1 : FROM windowsservercore
---> 5bc36a335344
Step 2 : SHELL powershell -command
---> Running in 87d7a64c9751
---> 4327358436c1
Removing intermediate container 87d7a64c9751
Step 3 : RUN New-Item -ItemType Directory C:\Example
---> Running in 3e6ba16b8df9
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/2/2016 2:59 PM Example
---> 1f1dfdcec085
Removing intermediate container 3e6ba16b8df9
Step 4 : ADD Execute-MyCmdlet.ps1 c:\example\
---> 6770b4c17f29
Removing intermediate container b139e34291dc
Step 5 : RUN c:\example\Execute-MyCmdlet -sample 'hello world'
---> Running in abdcf50dfd1f
Hello from Execute-MyCmdlet.ps1 - passed hello world
---> ba0e25255fda
Removing intermediate container abdcf50dfd1f
Successfully built ba0e25255fda
PS E:\docker\build\shell>
Die SHELL
Anweisung kann auch verwendet werden, um die Funktionsweise einer Shell zu ändern. Bei Verwendung von SHELL cmd /S /C /V:ON|OFF
unter Windows könnte die Erweiterungssemantik der verzögerten Umgebungsvariablen geändert werden.
Die SHELL
Anweisung kann auch unter Linux verwendet werden, wenn eine alternative Shell wie zsh, csh, tcsh und andere erforderlich ist.
Die SHELL
Funktion wurde in Docker 1.12 hinzugefügt.
Debian / Ubuntu-Pakete installieren
Führen Sie die Installation mit einem einzigen Ausführungsbefehl aus, um das Update zusammenzuführen und zu installieren. Wenn Sie später weitere Pakete hinzufügen, wird das Update erneut ausgeführt und alle benötigten Pakete installiert. Wenn das Update separat ausgeführt wird, wird es zwischengespeichert, und die Paketinstallation kann fehlschlagen. Das Setzen des Frontends auf nicht interaktiv und das Übergeben von -y zur Installation ist für Skriptinstallationen erforderlich. Durch das Reinigen und Löschen am Ende der Installation wird die Größe der Ebene minimiert.
FROM debian
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
git \
openssh-client \
sudo \
vim \
wget \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*