Kleinere Container erstellen

Auf dieser Seite wird beschrieben, wie Sie kleinere Docker-Images erstellen.

Kleinere Container erstellen

Beim Containerisieren einer Anwendung werden manchmal Dateien, die zur Laufzeit nicht benötigt werden, z. B. Abhängigkeiten bei der Build-Erstellung oder Zwischendateien, versehentlich in das Container-Image aufgenommen. Diese nicht benötigten Dateien erhöhen potenziell die Größe des Container-Images und verursachen dann zusätzlichen Zeitaufwand und zusätzliche Kosten, wenn das Image zwischen der Docker-Registry und der Containerlaufzeit verschoben wird.

Zur Reduzierung der Größe des Container-Images trennen Sie die Erstellung der Anwendung mit den dafür verwendeten Tools von der Zusammenstellung des Laufzeitcontainers.

Cloud Build bietet eine Reihe von Docker-Containern mit gängigen Entwicklertools wie Git, Docker und der Google Cloud CLI. Mit diesen Tools können Sie eine Build-Konfigurationsdatei für das Erstellen der Anwendung in einem Schritt und für das Zusammenstellen der endgültigen Laufzeitumgebung in einem weiteren Schritt definieren.

Wenn Sie beispielsweise eine Java-Anwendung erstellen, die Dateien wie den Quellcode, Anwendungsbibliotheken, Build-Systeme, Build-Systemabhängigkeiten und das JDK erfordert, haben Sie möglicherweise ein Dockerfile, das so aussieht:

FROM java:8

COPY . workdir/

WORKDIR workdir

RUN GRADLE_USER_HOME=cache ./gradlew buildDeb -x test

RUN dpkg -i ./gate-web/build/distributions/*.deb

CMD ["/opt/gate/bin/gate"]

Im obigen Beispiel lädt Gradle, das zum Erstellen des Pakets verwendet wird, eine große Anzahl von Bibliotheken zur Verwendung herunter. Diese Bibliotheken sind für das Erstellen des Pakets erforderlich, werden jedoch zur Laufzeit nicht benötigt. Alle Laufzeitabhängigkeiten sind im Paket gebündelt.

Mit jedem Befehl im Dockerfile wird eine neue Ebene im Container erstellt. Wenn in diesem Layer Daten generiert und nicht im selben Befehl gelöscht werden, kann dieser Speicherplatz nicht wiederverwendet werden. In diesem Fall lädt Gradle zum Ausführen des Builds Hunderte von Megabyte an Bibliotheken in das Verzeichnis cache herunter, die dann nicht gelöscht werden.

Eine effizientere Methode zur Ausführung des Builds ist die Verwendung von Cloud Build, um die Anwendung getrennt von ihrer Laufzeitebene zu erstellen.

Im folgenden Beispiel wird der Schritt zum Erstellen der Java-Anwendung von dem Schritt zum Zusammenstellen des Laufzeitcontainers getrennt:

YAML

  1. Anwendung erstellen: Fügen Sie cloudbuild.yaml einen Schritt zum Erstellen der Anwendung hinzu.

    Mit dem folgenden Code wird ein Schritt zum Erstellen des Images java:8 hinzugefügt. Dieses Image enthält den Java-Code.

    steps:
    
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    
    
  2. Laufzeitcontainer zusammenstellen: Fügen Sie in cloudbuild.yaml einen Schritt zum Zusammenstellen des Laufzeitcontainers hinzu.

    Mit dem folgenden Code wird ein Schritt namens gcr.io/cloud-builders/docker hinzugefügt. Damit wird der Laufzeitcontainer zusammengestellt. Dieser definiert den Laufzeitcontainer in einer eigenen Datei namens Dockerfile.slim.

    Im Beispiel wird die Alpine Linux-Basisebene openjdk:8u111-jre-alpine verwendet, die außergewöhnlich klein ist. Außerdem enthält es die JRE anstelle des umfangreicheren JDK, das zum Erstellen der Anwendung erforderlich war.

    cloudbuild.yaml
    
    steps:
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c',
             './gradlew gate-web:installDist -x test']
    
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest',
             '-f', 'Dockerfile.slim',
             '.'
      ]
    
    
    Dockerfile.slim
    
    FROM openjdk:8-jre-alpine
    
    COPY ./gate-web/build/install/gate /opt/gate
    
    CMD ["/opt/gate/bin/gate"]
    
  3. Erstellen Sie die Docker-Images: Fügen Sie cloudbuild.yaml einen Schritt zum Erstellen der Images hinzu.
    steps:
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest',
             '-f', 'Dockerfile.slim', '.']
    images:
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:latest'
    

JSON

  1. Anwendung erstellen: Fügen Sie cloudbuild.json einen Schritt zum Erstellen der Anwendung hinzu.

    Mit dem folgenden Code wird ein Schritt namens java:8 zum Erstellen des Java-Codes hinzugefügt.

    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
    }
    
  2. Laufzeitcontainer zusammenstellen: Fügen Sie in cloudbuild.json einen Schritt zum Zusammenstellen des Laufzeitcontainers hinzu.

    Mit dem folgenden Code wird ein Schritt namens gcr.io/cloud-builders/docker hinzugefügt. Damit wird der Laufzeitcontainer zusammengestellt. Dieser definiert den Laufzeitcontainer in einer eigenen Datei namens Dockerfile.slim.

    Im Beispiel wird die Alpine Linux-Basisebene openjdk:8u111-jre-alpine verwendet, die außergewöhnlich klein ist. Außerdem enthält es die JRE anstelle des umfangreicheren JDK, das zum Erstellen der Anwendung erforderlich war.

    cloudbuild.json:
    
    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
                "build",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:latest",
                "-f",
                "Dockerfile.slim",
                "."
            ]
        }
        ],
    }
    
    Dockerfile.slim:
    
    FROM openjdk:8u111-jre-alpine
    
    COPY ./gate-web/build/install/gate /opt/gate
    
    CMD ["/opt/gate/bin/gate"]
    
  3. Erstellen Sie die Docker-Images: Fügen Sie cloudbuild.json einen Schritt zum Erstellen der Images hinzu.
    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
                "build",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:latest",
                "-f",
                "Dockerfile.slim",
                "."
            ]
        }
        ],
        "images": [
            "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
            "gcr.io/$PROJECT_ID/$REPO_NAME:latest"
        ]
    }