Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Docker Image und Container erstellen

profile picture
Author
Svenja Michal
Published
2022-11-02
Time to read
17 minutes reading time

Einführung

In diesem Tutorial wird erklärt, wie man ein Docker Image entweder selbst aus einer Dockerfile erstellt oder von Docker Hub importiert, wie man aus einem Image einen Container erstellt und wie man ein Image und einen Container löscht. Docker muss dafür bereits auf dem Server installiert sein (siehe Docker installieren unter Ubuntu/Debian).

Wenn Sie einen neuen Hetzner Cloud Server erstellen und die Hetzner Cloud App Docker auswählen, wird docker-ce automatisch für Sie auf dem Server vorinstalliert.

Container
Docker Container werden aus einem sogenannten Image erstellt. Das Image definiert, was der Container genau enthalten soll. Das können bestimmte Dokumente sein, Befehle, die ausgeführt werden sollen oder andere Vorgaben. Ein Image kann man entweder als fertige Vorlage von Docker Hub importieren oder über eine Dockerfile selbst erstellen.

Dockerfile
Eine Dockerfile ist eine Datei, in der über mehrere Anweisungen definiert wird, was genau der Container einmal beinhalten soll. Aus dieser Dockerfile kann man ein Image erstellen, welches später als Basis für den definierten Container dient. Wenn man ein Image aus einer Dockerfile erstellt, wird für jede neue Anweisung innerhalb dieser Dockerfile ein eigenes Image erstellt. Dabei enthält jedes neuerstellte Image alle Images, die für darüberstehende Anweisungen erstellt wurden als sogenannte Layer. Ausschließlich das finale Image, also das Image, das mit der letzten Anweisung innerhalb der Dockerfile erstellt wird, besitzt einen eigenen Namen. Alle anderen Images sind sogenannte Intermediate Images mit dem Namen <none>.

Mit docker history <image> ist es möglich sich die verschiedenen Layer anzeigen zu lassen, die in einem Image enthalten sind. Da Intermediate Images keinen eigenen Namen besitzen, werden die Layer über die Image-ID unterschieden.

Intermediate Images
Der Zweck von Intermediate Images liegt mitunter vor allem darin, dass diese für mehrere Images verwendet werden können. Wenn also beispielsweise ein zweites Image genannt NEU erstellt wird, welches in den ersten beiden Anweisungen direkt mit einem bereits zuvor erstellten Image genannt ALT übereinstimmt, ist es möglich die entsprechenden Intermediate Images wiederzuverwenden. Das heißt, die ersten beiden Layer des Images NEU müssen nicht neu erstellt werden. Stattdessen werden direkt die bereits vorhandenen Intermediate Images über ihre Image-ID genutzt und der Erstellungsprozess des Images NEU kann schneller beendet werden. Da auf dem System keine zweiten Layer mit selbem Inhalt erstellt werden müssen, wird zusätzlich weniger Speicher vom Host benötigt.

Container
Docker Container bestehen im Wesentlichen aus zwei Teilen:

  • (Mehrere) schreibgeschützte Image Layer
  • Eine Container Layer

Ein einzelnes Image kann für mehrere Container verwendet werden. Wenn innerhalb eines Containers eine Änderung vorgenommen wird, die eines der Image Layer betrifft, wird dieses Image Layer nicht verändert. Stattdessen wird die Änderung in der Container Layer festgehalten.

Images
docker-container-create

Im obenstehenden Bild wird ein neues Image aus einer Dockerfile mit folgenden Anweisungen erstellt:

FROM ubuntu:latest
WORKDIR /new-dir
COPY file.txt .
CMD ["sleep", "60m"]

An erster Stelle steht immer FROM. Hier wird angegeben, worauf das neue Image aufbauen soll. In den meisten Fällen wird ein bereits existierendes Image verwendet. Da das nach FROM angegebene Image als Basis für das neue Image dient, wird dieses auch Parent Image genannt.

Das bei FROM angegebene Image wird erst auf dem System gesucht. In diesem Bild ist die aktuellste Version vom Image ubuntu bereits vorhanden und kann direkt verwendet werden. Wenn das Image nicht vorhanden ist, wird die Suche auf Docker Hub fortgesetzt und das Image wird automatisch importiert.

Wenn man kein Parent Image verwenden möchte, kann man auch FROM scratch angeben. In diesem Fall wird auf das leere scratch-Image von Docker Hub verwiesen. Da das Image nichts enthält, ist in den folgenden Intermediate Images und im finalen Image keine Layer für die FROM-Anweisung vorhanden. Diese Option eignet sich allerdings wenig für Anfänger. Images, die mit der Anweisung FROM scratch erstellt werden, werden Base Image genannt.

Voraussetzungen

  • Grundlegende Kenntnisse über Server
  • Docker ist bereits installiert (z. B. über die Hetzner App Docker CE oder das Tutorial Docker installieren unter Ubuntu/Debian)
  • Zugriff auf den root-Benutzer, einen Benutzer mit sudo-Rechten oder einen Benutzer in der Docker-Gruppe
  • Kommandozeile
  • Dieses Tutorial wurde anhand von Ubuntu 22.04 erstellt

Wenn Ihr Benutzer bisher noch nicht der Docker-Gruppe hinzugefügt wurde, können Sie beispielsweise dem zweiten Schritt im Tutorial zum Installieren von Docker folgen.

Beispiel-Benennungen

  • Image-Name/ID: <image>
  • Container-Name/ID: <container>

Beachten Sie, dass in allen Beispiel-Befehlen <image> mit dem eigenen Image-Namen oder der eigenen Image-ID und container mit dem eigenen Container-Namen oder der eigenen Container-ID ersetzt werden muss.

Schritt 1 - Docker Image erstellen

Wie oben bereits erklärt, benötigt jeder Docker Container ein Docker Image als Basis. Das heißt, bevor der erste Container erstellt werden kann, muss zunächst ein Image bereitgestellt werden. Dabei gibt es drei Möglichkeiten:

Folgend werden alle drei Optionen einzeln erklärt.

Für Anfänger eignet sich Option 1 am besten, ein Image von Docker Hub importieren.
Wenn Sie selbst bestimmen möchten, welche Änderungen im Dateisystem des Containers vorgenommen werden, können Sie Option 2 nutzen.

Option 1 - Fertiges Image von Docker Hub importieren

Beim Erstellen eines Containers aus einem Image von Docker Hub gibt es im Allgemeinen zwei wesentliche Befehle, docker pull und docker run.

  • Mit docker pull <image-name> ist es möglich ein beliebiges Image von Docker Hub zu importieren. Mit diesem Befehl wird noch kein Container erstellt.
  • Mit docker run <image-name> ist es möglich einen Container aus einem Image zu erstellen. Das im Befehl angegebene Image wird erst auf dem System gesucht. Wenn es dort nicht gefunden wird, wird die Suche anschließend auf Docker Hub fortgesetzt. Wenn dort ein passendes Image gefunden wird, wird es automatisch importiert. Anschließend wird aus diesem Image der neue Container erstellt.

Sie können also entweder erst docker pull nutzen, um das Image von Docker Hub zu importieren und daraus anschließend mit docker run einen oder mehrere neue Container erstellen oder Sie nutzen direkt docker run und führen damit beide Schritte mit einem Befehl aus:

docker run hello-world

Output:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world

...

Hello from Docker!
This message shows that your installation appears to be working correctly.

...

Im Output ist zu sehen, dass ein Image namens hello-world wie zuvor erwähnt erst auf dem System gesucht wurde. Nachdem keines gefunden wurde, wurde es automatisch von Docker Hub importiert. Sobald das Image auf dem System war, wurde daraus der neue Container erstellt.

Als nächstes können Sie mit dem Schritt Container starten und stoppen fortfahren. Falls Sie eine Terminal-Sitzung starten möchten, beachten Sie, dass das Image hello-world keine dauerhaft laufenden Prozesse beinhaltet.

Option 2 - Image manuell aus Dockerfile erstellen

Mit dieser Option legen Sie selbst fest, welche Layer Ihr Image besitzen soll und welche Konfigurationen und Einstellungen auf Ihrem Container vorgenommen werden sollen.

Um einen möglichst breiten Überblick über die verschiedenen Anweisungen zu geben, wird folgend ein Image für einen Container erstellt, welcher beim Erstellen:

  • ping installiert
  • Einen Ordner und eine Datei vom Host in den Container kopiert
  • Einen neuen Ordner und eine neue Datei im Container erstellt
  • Einen sleep-Befehl ausführt

Als ersten Schritt empfiehlt es sich einen neuen Ordner anzulegen. Hier können dann alle Dateien hinterlegt werden, die für das Erstellen des Containers relevant sind.

  • Neuen Ordner für das Image erstellen

    mkdir first-docker-image
  • Dateien anlegen, die kopiert werden sollen

    Öffnen Sie den neuen Ordner und erstellen Sie darin einen weiteren Ordner und eine Datei, die später in den Container kopiert werden sollen.

    cd first-docker-image
    mkdir copy-dir
    touch copy-file
  • Dateien anlegen, die nicht kopiert werden sollen

    In der Dockerfile müssen die Dateien nicht einzeln angegeben werden. Stattdessen kann mit einer Anweisung bestimmt werden, dass alle Dateien aus einem bestimmten Ordner kopiert werden sollen. Das wird praktisch, sobald man ein echtes Projekt mit wesentlich mehr als zwei Dateien erstellt. Für den Fall, dass eine der Dateien aber nicht kopiert werden soll, gibt es die .dockerignore-Datei. Alle Dateien, die darin gelistet sind, werden ignoriert und nicht in den Container kopiert.

    Testen Sie die .dockerignore-Datei, indem Sie eine Datei erstellen, die nicht kopiert werden soll:

    touch do-not-copy

    Erstellen Sie nun die .dockerignore-Datei und geben Sie alle Dateien an, die nicht kopiert werden sollen.

    nano .dockerignore

    Fügen Sie folgende Dateien hinzu:

    .dockerignore
    Dockerfile
    do-not-copy

    Anstatt alle Dokumente zu kopieren und in der .dockerignore-Datei die Ausnahmen zu listen, ist es auch möglich in der .dockerignore-Datei festzulegen, dass alle Dateien ignoriert werden sollen und Ausnahmen zu bestimmen. Dies würde dann so aussehen:

    *
    !copy-dir
    !copy-file

    Mit * wird angegeben, dass alle Dateien ignoriert und damit nicht kopiert werden sollen. Mit ! ist es möglich Ausnahmen zu bestimmen. In diesem Fall bedeutet das, dass ausschließlich die Dateien copy-dir und copy-file kopiert werden.

    Sobald Sie fertig sind, können Sie die Datei mit CTRL + X schließen, mit Y speichern und mit ENTER bestätigen.

  • Dockerfile anlegen

    nano Dockerfile

    Fügen Sie folgenden Text der Datei hinzu:

    FROM ubuntu:latest
    RUN apt update && apt install -y iputils-ping
    WORKDIR /new-workdir
    COPY . .
    RUN touch new-file
    RUN mkdir new-dir
    CMD ["sleep", "60m"]

    Sobald Sie fertig sind, können Sie die Datei mit CTRL + X schließen, mit Y speichern und mit ENTER bestätigen.

    Hinweis: Nach FROM wird angegeben, worauf das neue Image aufbauen soll. In diesem Beispiel, wird die aktuellste Version von Ubuntu verwendet. Wenn das Image noch nicht auf dem System ist, wird es automatisch von Docker Hub importiert.
    Nach COPY wird angegeben, welche Datei oder welcher Ordner kopiert werden soll. Anschließend wird der Pfad angegeben, unter dem die kopierte Datei auf dem Container gespeichert werden soll. Der erste . bedeutet, dass die Dateien aus dem Pfad kopiert werden sollen, unter dem man den Befehl ausführt. Der zweite . bedeutet, dass die Dateien unter dem Pfad gespeichert werden sollen, unter dem die Befehle auf dem Container ausgeführt werden. In diesem Fall ist das der Pfad /new-workdir, der zuvor mit WORKDIR festgelegt wurde. WORKDIR in einer Dockerfile kann mit cd in einer Kommandozeile verglichen werden.

  • Image aus Dockerfile erstellen

    Nutzen Sie nun folgenden Befehl, um aus der eben erstellten Dockerfile ein neues Image zu erstellen:

    docker build -t <image-name>:latest .

    Beachten Sie, dass <image-name> mit einem beliebigen Namen für das Image ersetzt werden muss. Mit der Option -t kann man einen Tag festlegen, im Format name:version. Zuletzt wird der Pfad angegeben, unter dem die Dockerfile zu finden ist, wobei . bedeutet, dass sich die Datei in dem Pfad befindet unter dem man gerade den Befehl ausführt.

  • Images listen

    Nutzen Sie folgenden Befehl, um sich ihr neues Image listen zu lassen:

    docker image ls

    Das neue Image kann nun genutzt werden, um einen neuen Container zu erstellen.

  • Container aus diesem Image erstellen

    Fahren Sie nun mit dem Schritt Container erstellen fort, um aus dem Image einen Container zu erstellen. Beachten Sie hierbei, dass in der Dockerfile ein sleep-Befehl enthalten ist, der direkt ausgeführt wird. Damit besitzt der Container nach dem Erstellen für 60 Minuten einen laufenden Prozess. Sobald der sleep-Befehl endet, wird der Container automatisch gestoppt. Wenn Sie den Container neustarten, wird auch der Befehl erneut ausgeführt.

    Nachdem der Container erstellt wurde, können Sie auf diesem eine Terminal-Sitzung starten. Wenn Sie sich anschließend mit ls alle Dokumente innerhalb Ihres Containers listen lassen, sollten die kopierten Dateien copy-dir und copy-file angezeigt werden, sowie die im Erstellungsprozess des Containers neu hinzugefügten Dateien new-file und new-dir.

Option 3 - Neues Image aus einem bestehenden Container erstellen

Ein einzelnes Image kann zum Erstellen mehrere Container verwendet werden. Änderungen, die innerhalb eines Containers vorgenommen werden, wirken sich nie auf andere Container aus. Um neue Container erstellen zu können, welche neben den Layern eines bestimmten Images auch die Änderungen beinhalten, die innerhalb eines Containers vorgenommen wurden, muss aus diesem Container zunächst ein neues Image erstellt werden. Das neue Image besitzt dann eine zusätzliche Layer, welche alle Änderungen enthält, die auf dem Container vorgenommen wurden.

  • Container listen

    docker container ls -a

    Kopieren Sie die ID oder den Namen des Containers aus dem Sie das Image erstellen wollen.

  • Image aus Container erstellen

    docker commit <container>

    Beachten Sie, dass <container> mit dem Container-Namen oder der Container-ID aus dem vorangegangenen Schritt ersetzt werden muss.

  • Images listen

    docker image ls

    Das eben erstellte Image sollte nun gelistet werden. Entnehmen Sie dem Output die dazugehörige ID, um dem Image im nächsten Schritt einen Namen geben zu können.

  • Image benennen

    docker tag <image-id> <name>

    Beachten Sie, dass <image-id> mit der ID des eben erstellten Images ersetzt werden muss und <name> mit einem selbst gewählten Namen, der dem Image nun zugewiesen werden soll.

Das eben erstellte Image kann nun wie alle anderen Images verwendet werden, um einen neuen Container zu erstellen.

Schritt 2 - Container erstellen

Ein einzelnes Image kann zum Erstellen von mehreren Containern genutzt werden. Solange zu einem bestimmten Image mindestens ein Container existiert, kann dieses Image nicht gelöscht werden.

  • Images listen

    docker image ls

    Kopieren Sie die ID oder den Namen des Images, aus dem der Container erstellt werden soll.

  • Container erstellen

    Bestehende Container können den Status laufend oder gestoppt besitzen.

    Solange auf einem Container mindestens ein Prozess läuft, besitzt dieser den Status "laufend". Sobald auf einem Container der letzte Prozess beendet wird, wird der Container ebenfalls automatisch "gestoppt". Dies ist dann relevant, wenn Sie auf Ihrem Container eine Terminal-Sitzung starten möchten. Denn eine Terminal-Sitzung kann ausschließlich auf einem Container mit laufenden Prozessen gestartet werden.

    Folgend werden 2 Optionen zum Erstellen eines Containers erklärt.

    • Option 1 eignet sich für die meisten Fälle und ist die empfohlene Option. Mit dieser Option wird der Container erst aus einem Image erstellt und anschließend direkt gestartet.
    • Option 2 eignet sich ausschließlich, wenn Sie auf Ihrem Container eine Terminal-Sitzung starten müssen und der Container nach dem Erstellen keine laufenden Prozesse besitzen würde. Damit Sie dennoch eine Terminal-Sitzung starten können, wird mit Option 2 bereits beim Erstellen des Containers ein erster Prozess gestartet.

    Option 1: Container aus Image erstellen und starten empfohlen
    Option 2: Container aus Image erstellen und gleichzeitig einen neuen Prozess starten

    Option 1 - Container aus Image erstellen und starten

    • Container erstellen

      docker run -d <image>

      Beachten Sie, dass <image> mit dem zuvor kopierten Namen oder der ID Ihres Images ersetzt werden muss. Mit der Option -d wird angegeben, dass der Container im Hintergrund laufen soll, und dass die Container-ID angezeigt werden soll.

      Das im Befehl angegebene Image wird erst auf dem System gesucht. Wenn es dort nicht gefunden wird, wird die Suche anschließend auf Docker Hub fortgesetzt. Wenn dort ein passendes Image gefunden wird, wird es automatisch importiert. Anschließend wird aus dem angegebenen Image der neue Container erstellt und gestartet.

    Option 2 - Container aus Image erstellen und gleichzeitig einen neuen Prozess starten

    Damit der Container nach dem Erstellen nicht automatisch gestoppt wird, kann im Befehl zum Erstellen des Containers gleichzeitig ein erster Prozess gestartet werden. Dabei gibt es unter anderem diese beiden Möglichkeiten:

    • Container erstellen und einen zeitlich begrenzten Prozess starten

      docker run -it <image>

      Mit dem obenstehenden Befehl wird direkt beim Erstellen des Containers eine Terminal-Sitzung geöffnet. Diese Sitzung ist ein eigener laufender Prozess.

      In der Befehlseingabe sollte nun nicht mehr der Hostname angeben werden, sondern die Container-ID oder der Container-Hostname. Alle Befehle werden nun auf dem Container ausgeführt. Um die Sitzung zu beenden, können Sie exit ausführen. Wenn Sie während der Sitzung keine weiteren Prozesse gestartet haben und die Sitzung beenden, wird der Container automatisch gestoppt. Um den Container anschließend wieder starten zu können, müssen Sie docker start -ai <container> ausführen und damit erneut eine Terminal-Sitzung starten. Dieser Befehl funktioniert nur bei gestoppten Containern, die wie in diesem Schritt mit den Optionen -it erstellt wurden.

    • Container erstellen und einen dauerhaften Prozess starten

      docker run -d <image> sleep infinity

      Mit der Option -d wird angegeben, dass der Container im Hintergrund laufen soll, und dass die Container-ID angezeigt werden soll.

      Mit dem obenstehenden Befehl wird direkt beim Erstellen des Containers ein sleep-Befehl ausgeführt. Solange dieser Prozess läuft, wird auch der Container nicht gestoppt.

Schritt 3 - Terminal-Sitzung im Container starten

Um eine neue Terminal-Sitzung in einem Container starten zu können, darf dieser nicht gestoppt sein. Wie in Schritt 2 bereits erklärt, bedeutet das, dass der Container mindestens einen laufenden Prozess besitzen muss.

  • Laufende Container listen

    docker container ls

    Wenn Sie im Befehl die Option -a ergänzen, werden zusätzlich auch alle gestoppten Container gelistet.

    Entnehmen Sie dem Output die ID oder den Namen des Containers, auf den Sie gerne zugreifen würden.

  • Terminal-Sitzung im Container starten

    docker exec -it <container> /bin/bash

    Sobald die Sitzung gestartet wurde, sollte in der Befehlseingabe nicht mehr der Name des Hosts angegeben werden, sondern die ID bzw. der Hostname Ihres Containers. Alle Befehle, die Sie in der Befehlseingabe eingeben, werden nun auf dem Container ausgeführt. Um das zu prüfen, können Sie sich mit ls -al beispielsweise alle Dateien des Containers anzeigen lassen. Mit hostname -I können Sie sich die IP-Adresse(n) des Containers anzeigen lassen.

  • Terminal-Sitzung im Container beenden

    exit

    Die Sitzung sollte nun beendet sein und in der Befehlseingabe sollte nun wieder der Name Ihres Hosts angegeben werden.

Schritt 4 - Container starten und stoppen

Einen Container zu starten bedeutet im Wesentlichen die im Container, bzw. dem dazugehörigen Image, enthaltenen Prozesse zu starten. Den Container zu stoppen bedeutet hingegen für alle laufenden Prozesse im Container den Stop zu erzwingen.

  • Container listen

    docker container ls -a

    Kopieren Sie die ID oder den Namen des Containers, den Sie starten oder stoppen wollen.

  • Container starten

    docker start <container>

    Beachten Sie, dass <container> mit dem eigenen Container-Namen oder der eigenen Container-ID ersetzt werden muss.

  • Container stoppen

    docker stop <container>

    Beachten Sie, dass <container> mit dem eigenen Container-Namen oder der eigenen Container-ID ersetzt werden muss.

Schritt 5 - Image oder Container löschen

  • Alle Images oder Container listen

    docker image ls
    docker container ls -a

    Kopieren Sie die ID oder den Namen des Images oder des Containers, den Sie löschen wollen.

  • Container löschen

    docker container rm <container>

    Beachten Sie, dass <container> mit dem eigenen Container-Namen oder der eigenen Container-ID ersetzt werden muss.

  • Image löschen

    docker image rm <image>

    Beachten Sie, dass <image> mit mit dem eigenen Image-Namen oder der eigenen Image-ID ersetzt werden muss.

    Beachten Sie, dass ein Image nur dann gelöscht werden kann, wenn keine vorhandenen Container auf diesem Image basieren. Sollte ein Container dieses Image nutzen, muss der Container gelöscht werden, bevor das Image gelöscht werden kann.

Ergebnis

Im vorangegangenen Tutorial haben Sie gelernt wie Sie ein Image aus einer Dockerfile erstellen oder von Docker Hub importieren, einen Container erstellen, eine Terminal-Sitzung in einem Container starten und wie Sie ein Image oder einen Container löschen. Als nächsten Schritt können Sie beispielsweise mit dem Tutorial IPv6 on Docker securely (EN) oder Run multiple Docker Compose services on Debian/Ubuntu (EN) fortfahren.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get 20€ free credit!

Valid until: 31 December 2024 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more