Ein Anwendungsimage in ECR veröffentlichen

AWSBeginner
Jetzt üben

Einführung

Dein Team möchte eine kleine HTTP-Anwendung ausliefern. Paketiere den bereitgestellten Code als Containerimage, speichere es in Amazon Elastic Container Registry (ECR) und beweise, dass genau diese Version startet und eine Anfrage beantwortet. Lass das separate Referenz-Repository unverändert und entferne anschließend deine Ressourcen.

Schließe zuerst AWS Foundations und die Grundlagen der IAM-Identitätsrichtlinien ab. Docker-Begriffe werden hier erklärt; eigener Anwendungscode oder ein persönliches AWS-Konto sind nicht erforderlich. Diese unabhängige VM stellt konfigurierte AWS CLI, Docker, Dockerfile und Quellcode bereit. Verwende AWS View oben zum Beobachten und Testen sowie Terminal unten für Befehle. Beide lesen denselben Ressourcenstatus.

Zertifizierungsbezug

Zertifizierung Prüfungsaufgabe Übung
Developer – Associate (DVA-C02) Aufgabe 3.1, Fähigkeit 3.1.1 Anwendungscode und Laufzeit für die Bereitstellung in ein Containerimage paketieren.

Laborübersicht

Konzeptdiagramm: Anwendung bauen, Image nach ECR übertragen, den exakten Digest abrufen und einen Docker-Container mit HTTP-Antwort starten.

Ein unveränderliches Image-Repository erstellen

In diesem Schritt erstellst du das Repository für deine Anwendungsversion.

Ein Image enthält Anwendungsdateien und Laufzeit. Ein Container ist eine laufende Instanz eines Images. Eine Registry speichert und verteilt Images; ein ECR-Repository gruppiert die Images einer Anwendung. Das Speichern startet die Anwendung nicht.

Wechsle in den vorbereiteten Arbeitsbereich und lies das Dockerfile. cat gibt eine Textdatei aus:

cd /home/labex/project
cat application/Dockerfile

FROM wählt das Python-Basisimage, COPY fügt die Anwendung hinzu, USER wählt einen Benutzer ohne erhöhte Rechte und CMD legt den Startbefehl fest. Die sha256-Basisreferenz fixiert den Inhalt des Basisimages, nicht den deines neuen Anwendungsimages.

Erstelle ct-demo. Ein Tag ist ein lesbarer Name wie release-1. IMMUTABLE verhindert, dass ein vorhandener Tag durch anderen Inhalt ersetzt wird, und hält Versionsnamen zuverlässig:

aws ecr create-repository \
  --repository-name ct-demo \
  --image-tag-mutability IMMUTABLE

Die Antwort enthält repositoryUri, die von Docker verwendete Adresse, und imageTagMutability: IMMUTABLE. Speichere die URI in einer Shellvariablen. $(...) übernimmt die Befehlsausgabe; --query wählt ein Feld und --output text entfernt JSON-Anführungszeichen:

REPOSITORY_URI=$(aws ecr describe-repositories \
  --repository-names ct-demo \
  --query 'repositories[0].repositoryUri' \
  --output text)
echo "$REPOSITORY_URI"

Lass diese Terminal-Sitzung geöffnet, damit die Variablen erhalten bleiben. In AWS View oben erscheint ct-demo mit null Images neben ct-reference. Das Referenz-Repository gehört zu einer anderen Anwendung und bleibt von deiner Bereinigung ausgenommen.

Die Version bauen und veröffentlichen

In diesem Schritt baust du die bereitgestellte Anwendung und überträgst ihr Image nach ECR.

Vor dem Push benötigt Docker eine Registry-Anmeldung. Die Registry-Adresse ist der Teil der URI vor dem ersten Schrägstrich. ${REPOSITORY_URI%%/*} entfernt diesen und alles danach:

REGISTRY=${REPOSITORY_URI%%/*}
echo "$REGISTRY"

Fordere über AWS CLI ein kurzlebiges ECR-Passwort an und leite es direkt an Docker weiter. | verbindet die Befehle; --password-stdin verhindert, dass das Passwort in Argumenten oder Terminal-Ausgaben erscheint. Gib es nicht selbst aus und speichere es nicht separat:

aws ecr get-login-password | docker login \
  --username AWS \
  --password-stdin "$REGISTRY"

Docker meldet Login Succeeded. Das erlaubt nur die deiner Identität gewährten Registry-Aktionen, keinen Zugriff auf jedes Repository.

Baue aus application. -t benennt das Ergebnis mit Repository-URI und Versions-Tag. Das letzte Argument ist der Build-Kontext, dessen Dateien COPY verwenden kann:

docker build -t "${REPOSITORY_URI}:release-1" application

Übertrage das Image. Docker lädt die Dateisystemschichten und das Manifest hoch, das den Inhalt beschreibt:

docker push "${REPOSITORY_URI}:release-1"

Am Ende zeigt Docker einen Digest sha256:.... Ein Digest identifiziert exakten Inhalt; ein Tag ist ein Name. Auch wenn ein Repository Tag-Änderungen erlaubt, bleibt der Digest an den ursprünglichen Inhalt gebunden.

Frage ECR ab, um die gespeicherte Version zu bestätigen:

aws ecr describe-images \
  --repository-name ct-demo \
  --image-ids imageTag=release-1 \
  --query 'imageDetails[0].{Tags:imageTags,Digest:imageDigest}'

Speichere den Digest außerdem in einer Variablen:

IMAGE_DIGEST=$(aws ecr describe-images \
  --repository-name ct-demo \
  --image-ids imageTag=release-1 \
  --query 'imageDetails[0].imageDigest' \
  --output text)

Der ECR-Digest muss mit der Ausgabe von docker push übereinstimmen. In AWS View oben enthält ct-demo nun release-1 und dessen Digest. Die Anwendung läuft noch nicht; du startest sie im nächsten Schritt.

Das exakt veröffentlichte Image ausführen

In diesem Schritt lädst du das Image per Digest und prüfst einen tatsächlichen Anwendungscontainer.

Entferne zuerst das lokal gebaute Image. docker image rm entfernt eine lokale Referenz, nicht das in ECR gespeicherte Image. Der nächste Pull ruft damit die veröffentlichte Version ab:

docker image rm "${REPOSITORY_URI}:release-1"

Verbinde URI und Digest mit @, um den exakten Inhalt auszuwählen:

docker pull "${REPOSITORY_URI}@${IMAGE_DIGEST}"

Docker meldet denselben Digest und einen erfolgreichen Download. Starte ihn als ct01-app. --detach führt im Hintergrund aus; --publish 127.0.0.1:8081:8000 verbindet Host-Port 8081 mit Anwendungsport 8000. Die Loopback-Adresse begrenzt direkten Zugriff auf diese VM. Das Image wählt bereits einen Benutzer ohne erhöhte Rechte; --read-only macht das Root-Dateisystem schreibgeschützt, --cap-drop ALL entfernt Linux-Capabilities und no-new-privileges verhindert zusätzliche Rechte:

docker run --detach \
  --name ct01-app \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --memory 256m \
  --publish 127.0.0.1:8081:8000 \
  "${REPOSITORY_URI}@${IMAGE_DIGEST}"

Eine Container-ID bedeutet, dass Docker den Start akzeptiert hat, belegt aber keine funktionierende Anwendung. Prüfe HTTP: curl --fail schlägt bei HTTP-Fehlern fehl; --retry-all-errors wiederholt Startfehler, einschließlich eines kurzen Verbindungsabbruchs:

curl --fail --silent --show-error \
  --retry 5 --retry-all-errors --retry-delay 1 \
  http://127.0.0.1:8081/

Erwarte JSON mit "release": "release-1" und dem Container-Hostnamen. Prüfe die Logs auf die tatsächliche Anfrage:

docker logs ct01-app

Du solltest served application request sehen. Hostname und Zeitstempel variieren. Wähle in AWS View oben Request application. Auch diese Antwort muss release-1 zeigen; die Schaltfläche sendet eine tatsächliche HTTP-Anfrage an den Container.

Tatsächlicher AWS-View-Zustand: ECR enthält release-1 und dessen Digest, und die Docker-Anwendung antwortet mit derselben Version. Digest und Hostname sind Beispielwerte dieses Durchlaufs.

Deine Anwendungsressourcen entfernen

In diesem Schritt stoppst du die Anwendung und entfernst ihr lokales Image und ECR-Repository, während das Referenz-Repository erhalten bleibt.

Stoppe zunächst den Container:

docker stop ct01-app

Entferne ihn anschließend. Das Entfernen eines Containers löscht sein Image nicht:

docker rm ct01-app

Kein laufender Container verwendet das Image mehr; entferne die lokale Digest-Referenz:

docker image rm "${REPOSITORY_URI}@${IMAGE_DIGEST}"

Lösche das Image in ECR per Digest. imageDigest wählt den exakten Inhalt, statt sich auf einen Tag zu verlassen:

aws ecr batch-delete-image \
  --repository-name ct-demo \
  --image-ids imageDigest="$IMAGE_DIGEST"

Die Antwort muss das gelöschte Image unter imageIds und eine leere Liste failures zeigen. Entferne das jetzt leere Anwendungs-Repository:

aws ecr delete-repository --repository-name ct-demo

Bestätige, dass das Referenz-Repository erhalten bleibt:

aws ecr describe-repositories \
  --query 'repositories[].repositoryName'

Erwarte ausschließlich ct-reference. Entferne zuletzt die von Docker gespeicherte Registry-Anmeldung:

docker logout "$REGISTRY"

In AWS View oben verschwinden ct-demo und der Anwendungscontainer; das Referenz-Repository bleibt. Ein HTTP-Fehler allein beweist keine Bereinigung. Du hast zusätzlich das Inventar geprüft sowie den tatsächlichen Container und das Image entfernt.

Zusammenfassung

Du hast ein unveränderliches ECR-Repository erstellt, ein Image gebaut und veröffentlicht, den Digest verglichen und genau diese Version ausgeführt. Du hast tatsächliche HTTP-Antworten und Logs geprüft und deinen Container, dein lokales Image und dein Repository entfernt, während das einer anderen Anwendung erhalten blieb. Das nächste Labor verwendet eine ECS-Task-Definition zur Auswahl und Ausführung eines Images.

Weitere Informationen bietet die AWS-Dokumentation: Registry-Authentifizierung und Image-Push; Überschreiben von Image-Tags verhindern.