よりスリムなコンテナのビルド

このページでは、よりスリムな Docker イメージをビルドする方法について説明します。

よりスリムなコンテナをビルドする

アプリケーションをコンテナ化する際に、ビルド時の依存関係や中間ファイルといった、ランタイムに不要なファイルが誤ってコンテナ イメージに含まれることがあります。こうした不要なファイルによってコンテナ イメージのサイズが拡大し、Docker レジストリとコンテナのランタイムとの間でイメージを移動するときに余計な時間と費用がかかる可能性があります。

コンテナ イメージのサイズを小さくするには、アプリケーションのビルドをビルド用のツールとともに、ランタイム コンテナの組み立てから分離します。

Cloud Build には、Git、Docker、Google Cloud CLI などの一般的なデベロッパー ツールを備えた一連の Docker コンテナがあります。これらのツールを使用して、アプリケーションをワンステップでビルドし、別のステップで最終的なランタイム環境を組み立てるようにビルド構成ファイルを定義します。

たとえば、Java アプリケーションを構築する場合、ソースコード、アプリケーション ライブラリ、ビルドシステム、ビルドシステムの依存関係、JDK などのファイルが必要になります。Dockerfile は次のようになります。

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"]

上の例では、パッケージのビルドに使用される Gradle が多数のライブラリをダウンロードします。これらのライブラリは、パッケージのビルドには不可欠ですが、ランタイムには不要です。ランタイム依存関係はすべてパッケージにバンドルされています。

Dockerfile の各コマンドは、コンテナ内に新しいレイヤを作成します。このレイヤにデータが生成され、同じコマンドで削除されない場合、その領域は回復できません。この場合、Gradle はビルドを実行するために数百 MB のライブラリを cache ディレクトリにダウンロードしていますが、これらのライブラリは削除されません。

ビルドをより効率的に実行するには、Cloud Build を使用して、アプリケーションのビルドとランタイム レイヤのビルドを分離します。

次の例では、Java アプリケーションをビルドするステップとランタイム コンテナを構築するステップを分けています。

YAML

  1. アプリケーションをビルドする: cloudbuild.yaml に、アプリケーションのビルドステップを追加します。

    次のコードでは、java:8 イメージのビルドステップを追加しています。ここには、Java コードが含まれています。

    steps:
    
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    
    
  2. ランタイム コンテナを作成する: cloudbuild.yaml に、ランタイム コンテナの作成ステップを追加します。

    次のコードでは、ランタイム コンテナの作成ステップを gcr.io/cloud-builders/docker という名前で追加しています。ランタイム コンテナは、Dockerfile.slim という別のファイルに定義されています。

    この例では、Alpine Linux ベースレイヤ openjdk:8u111-jre-alpine を使用しています。ここには、必要な最低限のものが含まれています。アプリケーションの作成に必要な JDK ではなく、JRE が含まれています。

    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. Docker イメージを作成する: 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', '.']
    images:
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:latest'
    

JSON

  1. アプリケーションをビルドする: cloudbuild.json に、アプリケーションのビルドステップを追加します。

    次のコードでは、Java コードをビルドするために java:8 という名前のステップを追加しています。

    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
    }
    
  2. ランタイム コンテナを作成する: cloudbuild.json に、ランタイム コンテナの作成ステップを追加します。

    次のコードでは、ランタイム コンテナの作成ステップを gcr.io/cloud-builders/docker という名前で追加しています。ランタイム コンテナは、Dockerfile.slim という別のファイルに定義されています。

    この例では、Alpine Linux ベースレイヤ openjdk:8u111-jre-alpine を使用しています。ここには、必要な最低限のものが含まれています。アプリケーションの作成に必要な JDK ではなく、JRE が含まれています。

    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. Docker イメージを作成する: 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",
                "."
            ]
        }
        ],
        "images": [
            "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
            "gcr.io/$PROJECT_ID/$REPO_NAME:latest"
        ]
    }