マルチアーキテクチャビルドとイメージ、簡単な方法

「一度ビルドすれば、どこにでもデプロイする」というのは紙の上では素晴らしいことですが、Raspberry PisやAWS A1インスタンスなどのARMターゲットを使用して請求額を削減したり、古いi386サーバーを使い続けたりする場合は、どこにでもデプロイするのは難しい問題になる可能性がありますこれらのプラットフォーム用のソフトウェアを構築する必要があるため。 この問題を解決するために、Dockerはマルチアーキテクチャビルドの原則を導入し、これを使用して本番環境に配置する方法を見ていきます。

クイックセットアップ

このコマンドを使用できる docker manifest ようにするには、実験的な機能を有効にする必要があります。

macOSとウィンドウズでは、それは本当に簡単です。 環境設定>コマンドラインパネルを開き、実験的な機能を有効にします。

スクリーンショット 2020 04 23 で 16.43. 39

Linux では、エンジンを編集 ~/.docker/config.json して再起動する必要があります。

ボンネットの下

さて、マルチアーチ画像が興味深い理由はわかりましたが、どのように作成しますか? それらはどのように機能しますか?

各 Docker イメージは マニフェストで表されます。 マニフェストは、Docker イメージに関するすべての情報を含む JSON ファイルです。 これには、各レイヤー、対応するサイズ、画像のハッシュ、サイズ、および動作するプラットフォームへの参照が含まれます。 このマニフェストは、見つけやすいように タグ で参照できます。

たとえば、次のコマンドを実行すると、nightly-slimタグを持つrustlang/rustリポジトリ内の非マルチアーチイメージのマニフェストを取得します。

$ docker manifest inspect --verbose rustlang/rust:nightly-slim
{
  "Ref": "docker.io/amd64/rust:1.42-slim-buster",
  "Descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:1bf29985958d1436197c3b507e697fbf1ae99489ea69e59972a30654cdce70cb",
    "size": 742,
    "platform": {
      "architecture": "amd64",
      "os": "linux"
    }
  },
  "SchemaV2Manifest": {
    "schemaVersion": 2,
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": 4830,
      "digest": "sha256:dbeae51214f7ff96fb23481776002739cf29b47bce62ca8ebc5191d9ddcd85ae"
    },
    "layers": [
      {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 27091862,
      "digest": "sha256:c499e6d256d6d4a546f1c141e04b5b4951983ba7581e39deaf5cc595289ee70f"
      },
      {
        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
        "size": 175987238,
        "digest": "sha256:e2f298701fbeb02568c3dcb9822f8488e24ef12f5430bc2e8562016ba8670f0d"
      }
    ]
  }

}

問題は、それぞれが異なるアーキテクチャをサポートする複数のDockerイメージを同じタグの背後に配置するにはどうすればよいですか?

このマニフェストファイルにマニフェストのリストが含まれていて、Docker Engine が実行時に一致するマニフェストを選択できる場合はどうなりますか? これはまさに、マルチアーキテクチャイメージのマニフェストの構築方法です。 この種類のマニフェストは、マニフェスト リストと呼ばれます。

マルチアーチ画像を見てみましょう。

$ docker manifest inspect ‐‐verbose rust:1.42-slim-buster
[
  {
    "Ref": "docker.io/library/rust:1.42-slim-buster@sha256:1bf29985958d1436197c3b507e697fbf1ae99489ea69e59972a30654cdce70cb",
    "Descriptor": {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "digest": "sha256:1bf29985958d1436197c3b507e697fbf1ae99489ea69e59972a30654cdce70cb",
      "size": 742,
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    "SchemaV2Manifest": { ... }
  },
  {
    "Ref": "docker.io/library/rust:1.42-slim-buster@sha256:116d243c6346c44f3d458e650e8cc4e0b66ae0bcd37897e77f06054a5691c570",
    "Descriptor": {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "digest": "sha256:116d243c6346c44f3d458e650e8cc4e0b66ae0bcd37897e77f06054a5691c570",
      "size": 742,
      "platform": {
        "architecture": "arm",
        "os": "linux",
        "variant": "v7"
      }
    },
    "SchemaV2Manifest": { ... }
...
]

これは、すべての異なるイメージのマニフェストの単純なリストであり、それぞれに、Docker Engine がそれ自体を照合するために使用できるプラットフォーム セクションがあることがわかります。

それらがどのように作られているか

Docker を使用してマルチアーキテクチャ イメージを構築するには、 を使用する方法と docker buildxを使用するdocker manifest方法の 2 つがあります。

これを実証するには、再生するプロジェクトが必要です。 次の Dockerfile を使用しますが、これは curl バイナリを含む Debian ベースのイメージになります。

ARG ARCH=
FROM ${ARCH}debian:buster-slim

RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*

ENTRYPOINT [ "curl" ]

これで、マルチアーチイメージの構築を開始する準備が整いました。

ドッカーマニフェストの難しい方法

「dockerマニフェスト」は、マルチアーキテクチャイメージを構築するためにDockerによって作成された最も古いツールであるため、難しい方法で行うことから始めます。

まず、各アーキテクチャのイメージをビルドして Docker Hub にプッシュする必要があります。 次に、これらすべての画像をタグによって参照されるマニフェストリストに結合します。

# AMD64
$ docker build -t your-username/multiarch-example:manifest-amd64 --build-arg ARCH=amd64/ .
$ docker push your-username/multiarch-example:manifest-amd64

# ARM32V7
$ docker build -t your-username/multiarch-example:manifest-arm32v7 --build-arg ARCH=arm32v7/ .
$ docker push your-username/multiarch-example:manifest-arm32v7

# ARM64V8
$ docker build -t your-username/multiarch-example:manifest-arm64v8 --build-arg ARCH=arm64v8/ .
$ docker push your-username/multiarch-example:manifest-arm64v8

イメージをビルドしてプッシュしたので、コマンドを使用してマニフェストリストで docker manifest それらすべてを参照できます。

$ docker manifest create \
your-username/multiarch-example:manifest-latest \
--amend your-username/multiarch-example:manifest-amd64 \
--amend your-username/multiarch-example:manifest-arm32v7 \
--amend your-username/multiarch-example:manifest-arm64v8

マニフェスト リストが作成されたら、それを Docker Hub にプッシュできます。

$ docker manifest push your-username/multiarch-example:manifest-latest

ここで Docker Hub に移動すると、イメージを参照する新しいタグが表示されます。

スクリーンショット 2020 04 23 で 16.43. 39

ドッカービルドxを使用した簡単な方法

buildx はまだ実験段階であることに注意してください

MacまたはWindowsを使用している場合は、心配する必要はありませんが、buildxはDocker Desktopに同梱されています。 Linuxを使用している場合は、こちらのドキュメントに従ってインストールする必要があります https://github.com/docker/buildx

buildxの魔法は、上記のプロセス全体を1つのコマンドで実行できることです。

$ docker buildx build \
--push \
--platform linux/arm/v7,linux/arm64/v8,linux/amd64 \ --tag your-username/multiarch-example:buildx-latest .

これで、1つのコマンド、1つのタグ、複数の画像が完成しました。

スクリーンショット 2020 04 15 で 14.29. 45

本番環境に行きましょう

次に、CI をターゲットにし、GitHub Actions を使用してマルチアーキテクチャ イメージを構築し、ハブにプッシュします。

そのために、git リポジトリに配置する .github/workflows/image.yml 構成ファイルを作成します。

name: build our image

on:
  push:
    branches: master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: checkout code
        uses: actions/checkout@v2
      - name: install buildx
        id: buildx
        uses: crazy-max/ghaction-docker-buildx@v1
        with:
          version: latest
      - name: build the image
      run: |
        docker buildx build \
          --tag your-username/multiarch-example:latest \
          --platform linux/amd64,linux/arm/v7,linux/arm64 .

GitHub Action crazy-max/docker-buildx のおかげで、たった 1 つのステップで buildx をインストールして構成することができます。

プッシュできるようにするには、セキュリティ設定で Docker Hubでアクセストークン を取得する必要があります。

スクリーンショット 2020 04 15 で 14.19. 38

作成したら、[ シークレット ] セクションのリポジトリ設定で設定する必要があります。 後でログインするための変数を作成しますDOCKER_USERNAMEDOCKER_PASSWORD

スクリーンショット 2020 04 15 で 14.21. 09

これで、GitHub アクション構成ファイルを更新し、ビルドの前にログインステップを追加できます。 そして、コマンドに追加--pushbuildxできます。

...
      - name: login to docker hub
        run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
      - name: build the image
        run: |
          docker buildx build --push \
            --tag your-username/multiarch-example:latest \
            --platform linux/amd64,linux/arm/v7,linux/arm64 .

これで、マスターに何かがプッシュされるたびにイメージが構築され、プッシュされます。

結論

この投稿では、マルチアーキテクチャのDockerイメージを構築してDockerハブにプッシュする方法の例を示します。 また、GitHub アクションを使用して git リポジトリのこのプロセスを自動化する方法も示しました。しかし、これは他のCIシステムからも行うことができます。

Circle CI、Gitlab CI、Travis でマルチアーキテクチャイメージを構築する例については、 こちらを参照してください。