Was ist der Unterschied zwischen den Befehlen COPY
und ADD
in einer Docker-Datei, und wann würde ich einen über den anderen verwenden?
COPY <src> <dest>
Die COPY-Anweisung kopiert neue Dateien aus
<src>
und fügt sie dem Dateisystem des Containers unter dem Pfad<dest>
hinzu.
ADD <src> <dest>
Die ADD-Anweisung kopiert neue Dateien aus
<src>
und fügt sie dem Dateisystem des Containers unter dem Pfad<dest>
hinzu.
Sie sollten die Dokumentation zu ADD
und COPY
lesen, um eine ausführliche Beschreibung ihres Verhaltens zu erhalten. Der Hauptunterschied besteht jedoch darin, dass ADD
kann mehr als COPY
:
ADD
kann <src>
eine URL seinADD
Dokumentation eindeutig Folgendes angegeben: Wenn es sich um ein lokales tar-Archiv in einem erkannten Komprimierungsformat (identity, gzip, bzip2 oder xz) handelt, wird es als Verzeichnis entpackt. Ressourcen von entfernten URLs werden nicht dekomprimiert.
Beachten Sie, dass in Best Practices für das Schreiben von Dock-Dateien die Verwendung von COPY
empfohlen wird, wenn die Magie von ADD
nicht erforderlich ist. Andernfalls werden Sie (da Sie diese Antwort nachschlagen mussten) wahrscheinlich eines Tages überrascht sein, wenn Sie keep_this_archive_intact.tar.gz
In Ihren Container kopieren möchten, aber stattdessen sprühen Sie den Inhalt auf Ihr Dateisystem.
COPY
ist
Entspricht 'ADD', jedoch ohne die Behandlung von tar und entfernten URLs.
Referenz direkt aus dem Quellcode .
Zu diesem Punkt gibt es eine offizielle Dokumentation: Best Practices for Writing Dockerfiles
Da es auf die Bildgröße ankommt, wird dringend davon abgeraten,
ADD
zum Abrufen von Paketen von fernen URLs zu verwenden. Sie sollten stattdessencurl
oderwget
verwenden. Auf diese Weise können Sie die Dateien löschen, die Sie nach dem Extrahieren nicht mehr benötigen, und müssen Ihrem Bild keine weitere Ebene hinzufügen.
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.gz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
Für andere Elemente (Dateien, Verzeichnisse), für die die automatische Tar-Extraktionsfunktion von
ADD
nicht erforderlich ist, sollten Sie immerCOPY
verwenden.
In Docker-Dokumenten:
HINZUFÜGEN oder KOPIEREN
Obwohl ADD und COPY funktional ähnlich sind, wird COPY im Allgemeinen bevorzugt. Das liegt daran, dass es transparenter ist als ADD. COPY unterstützt nur das grundlegende Kopieren lokaler Dateien in den Container, während ADD einige Funktionen (wie die reine lokale Teer-Extraktion und die Unterstützung von Remote-URLs) bietet, die nicht sofort ersichtlich sind. Folglich ist die beste Verwendung für ADD die automatische Extraktion lokaler TAR-Dateien in das Image, wie in ADD rootfs.tar.xz /.
Wenn Sie einem /usr/local
-In-Container ein xx.tar.gz hinzufügen möchten, entpacken Sie es und entfernen Sie das unbrauchbare komprimierte Paket.
Für KOPIEREN:
COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local
RUN rm /tmp/jdk-7u79-linux-x64.tar.gz
Für ADD:
ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/
ADD unterstützt nur die lokale Teergewinnung. Außerdem verwendet COPY drei Ebenen, während ADD nur eine Ebene verwendet.
In Docker-Dokumenten: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy
"Obwohl ADD und COPY funktional im Allgemeinen ähnlich sind, wird COPY bevorzugt. Dies liegt daran, dass es transparenter als ADD ist. COPY unterstützt nur das grundlegende Kopieren lokaler Dateien in den Container, während ADD einige Funktionen aufweist (z (Unterstützung für Remote-URLs), die nicht sofort ersichtlich sind. Folglich ist die automatische Extraktion von lokalen TAR-Dateien in das Image die beste Verwendung für ADD, wie in ADD rootfs.tar.xz /.
Wenn Sie über mehrere Dockerfile-Schritte verfügen, die unterschiedliche Dateien aus Ihrem Kontext verwenden, KOPIEREN Sie diese einzeln und nicht alle auf einmal. Auf diese Weise wird sichergestellt, dass der Build-Cache jedes Schritts nur ungültig wird (wodurch ein erneuter Start des Schritts erzwungen wird), wenn sich die speziell erforderlichen Dateien ändern.
Zum Beispiel:
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
Führt zu weniger Cache-Invalidierungen für den RUN-Schritt als beim Kopieren./tmp/davor.
Da es auf die Bildgröße ankommt, wird dringend davon abgeraten, ADD zum Abrufen von Paketen von Remote-URLs zu verwenden. Sie sollten stattdessen Curl oder Wget verwenden. Auf diese Weise können Sie die Dateien löschen, die Sie nach dem Extrahieren nicht mehr benötigen, und müssen Ihrem Bild keine weitere Ebene hinzufügen. Sie sollten beispielsweise Folgendes vermeiden:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
Und machen Sie stattdessen etwas wie:
RUN mkdir -p /usr/src/things \
&& curl -SL htt,p://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
Für andere Elemente (Dateien, Verzeichnisse), für die keine automatische Tar-Extraktionsfunktion von ADD erforderlich ist, sollten Sie immer COPY verwenden. "
COPY
kopiert eine Datei/ein Verzeichnis von Ihrem Host auf Ihr Image.
ADD
kopiert eine Datei/ein Verzeichnis von Ihrem Host auf Ihr Image, kann aber auch entfernte URLs abrufen, TAR-Dateien extrahieren usw.
Verwenden Sie COPY
, um einfach Dateien und/oder Verzeichnisse in den Build-Kontext zu kopieren.
Verwenden Sie ADD
, um Remote-Ressourcen herunterzuladen, TAR-Dateien zu extrahieren usw.
COPY
Dadurch werden eine oder mehrere lokale Dateien oder Ordner in das Ziel in Ihrem Docker-Image kopiert.
COPY < src> < dest >
COPY ["< source >",... "< destination >"]
(Dieses Formular ist für Pfade mit Leerzeichen erforderlich.)
Ein Beispiel für eine Docker-Datei, die COPY
verwendet So würden Sie COPY
in einer Docker-Datei für eine Ruby App verwenden.
FROM Ruby:2.5.1
WORKDIR /usr/src/app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["./your-daemon-or-script.rb"]
Es baut das Bild in Ebenen auf, beginnend mit dem übergeordneten Bild Ruby: 2.5.1, das mit FROM definiert wurde.
Die Docker-Anweisung WORKDIR
definiert ein Arbeitsverzeichnis für die darauf folgenden Anweisungen COPY
oder ADD
.
Durch Kopieren von Gemfiles
gefolgt von RUN bundle install
wird eine Bildebene mit den installierten Ruby Gems erstellt, die zwischengespeichert werden können. In den letzten beiden Docker-Anweisungen werden die Dateien der App in das Image kopiert und der Standardbefehl mit CMD
festgelegt.
Wenn Sie also eine der App-Dateien ändern, können Sie das Docker-Image mithilfe der zwischengespeicherten übergeordneten Ebene und der Zwischenebene neu erstellen. Dies ist viel effizienter als alle von Grund auf neu zu erstellen.
_ _ hinzufügen
Diese Anweisung hat eine ähnliche Syntax wie COPY
.
ADD < src> < dest >
ADD ["< source >",... "< destination >"] (this form is required for paths containing whitespace)
Es kopiert nicht nur lokale Dateien und Verzeichnisse in das Ziel im Docker-Image, sondern bietet auch einige zusätzliche Funktionen:
Wenn <source>
ein lokales Tar-Archiv in einem erkannten Komprimierungsformat ist, wird es automatisch als Verzeichnis in das Docker-Image entpackt. Zum Beispiel: ADD rootfs.tar.xz /
Wenn der <source>
eine URL ist, wird die Datei heruntergeladen und in das Ziel im Docker-Image kopiert. Docker rät jedoch davon ab, ADD für diesen Zweck zu verwenden.
Best Practice Dockerfile zum Kopieren von einer URL
Docker schlägt vor, dass das Kopieren von einer URL mithilfe von ADD häufig nicht effizient ist, und es wird empfohlen, andere Strategien zu verwenden, um die erforderlichen Remotedateien einzuschließen.
Da es auf die Bildgröße ankommt, wird dringend davon abgeraten, ADD zum Abrufen von Paketen von Remote-URLs zu verwenden. Sie sollten stattdessen Curl oder Wget verwenden. Auf diese Weise können Sie die Dateien löschen, die Sie nach dem Extrahieren nicht mehr benötigen, und müssen Ihrem Bild keine weitere Ebene hinzufügen. - Bewährte Dockerfile-Methoden
Sie sollten beispielsweise Folgendes vermeiden:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
Und machen Sie stattdessen etwas wie:
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
Für andere Elemente (Dateien, Verzeichnisse), für die die automatische Tar-Extraktionsfunktion von ADD
nicht erforderlich ist, sollten Sie immer COPY
verwenden.
Quelle: https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile :
COPY und ADD sind Dockerfile-Anweisungen, die ähnlichen Zwecken dienen. Sie können Dateien von einem bestimmten Speicherort in ein Docker-Image kopieren.
COPY nimmt eine Quelle und ein Ziel auf. Sie können nur eine lokale Datei oder ein lokales Verzeichnis von Ihrem Host (dem Computer, auf dem das Docker-Image erstellt wurde) in das Docker-Image selbst kopieren.
Mit ADD können Sie dies auch tun, es werden jedoch auch 2 andere Quellen unterstützt. Erstens können Sie eine URL anstelle einer lokalen Datei/eines lokalen Verzeichnisses verwenden. Zweitens können Sie eine TAR-Datei von der Quelle direkt in das Ziel extrahieren
Ein gültiger Anwendungsfall für ADD ist, wenn Sie eine lokale tar-Datei in ein bestimmtes Verzeichnis in Ihrem Docker-Image extrahieren möchten.
Wenn Sie lokale Dateien in Ihr Docker-Image kopieren, verwenden Sie immer COPY, da dies expliziter ist.
Ich musste in meinem Docker-Image COPY
und Java entpacken. Wenn ich die mit ADD erstellte Docker-Bildgröße verglich, war sie 180 MB größer als die mit COPY erstellte, tar -xzf * .tar.gz und rm * .tar.gz
Dies bedeutet, dass ADD die TAR-Datei zwar entfernt, sie jedoch an einem beliebigen Ort aufbewahrt wird. Und es macht das Bild größer !!
Seit Docker 17.05 wird COPY
mit dem Flag --from
in mehrstufigen Builds verwendet, um Artefakte aus vorherigen Build-Phasen in die aktuelle Build-Phase zu kopieren.
aus der Dokumentation
Optional akzeptiert COPY ein Flag
--from=<name|index>
, mit dem der Quellspeicherort auf eine vorherige Erstellungsstufe (erstellt mit FROM .. AS) festgelegt werden kann, die anstelle eines vom Benutzer gesendeten Erstellungskontexts verwendet wird.
docker build -t {image name} -v {Host directory}:{temp build directory} .
Dies ist eine weitere Möglichkeit, Dateien in ein Bild zu kopieren. Die Option -v erstellt vorübergehend ein Volume, das wir während des Erstellungsprozesses verwendet haben.
Dies unterscheidet sich von anderen Volumes, da ein Hostverzeichnis nur für den Build bereitgestellt wird. Dateien können mit einem Standard-Befehl cp kopiert werden.
Ebenso wie curl und wget kann es in einem Befehlsstapel ausgeführt werden (wird in einem einzelnen Container ausgeführt), ohne die Bildgröße zu multiplizieren. ADD und COPY können nicht gestapelt werden, da sie in einem eigenständigen Container ausgeführt werden und nachfolgende Befehle für die Dateien, die in zusätzlichen Containern ausgeführt werden, die Bildgröße multiplizieren:
Mit den so eingestellten Optionen:
-v /opt/mysql-staging:/tvol
Folgendes wird in einem Container ausgeführt:
RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \
mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \
mkdir /u1/mysql/mysql-files && \
mkdir /u1/mysql/innodb && \
mkdir /u1/mysql/innodb/libdata && \
mkdir /u1/mysql/innodb/innologs && \
mkdir /u1/mysql/tmp && \
chmod 750 /u1/mysql/mysql-files && \
chown -R mysql /u1/mysql && \
chgrp -R mysql /u1/mysql