ENECHANGE Developer Blog

ENECHANGE開発者ブログ

Docker Build Cloudを本番CI/CDパイプラインに導入・検証してみた

ENECHANGE所属のエンジニア id:tetsushi_fukabori こと深堀です。
最近、愛犬のバーニーズマウンテンドッグが当たり前のように飼い主のベッドに乗って寝るようになりました。
飼い主の体の位置など何も気にしないので踏み潰されて起きることもしばしばです。
いつか痛い目を見ると思います(飼い主が)。


今回は2024年2月にオープンされたDocker Build Cloudを触ってみました。

www.docker.com

弊社ではコンテナで稼働するアプリケーションが増えてきており、コンテナイメージのビルドにはCodeBuildを使用しています。
CodeBuildと比較してのメリットや、Docker Build CloudをCodePipelineのパイプラインへどう組み込むかについても解説します。

なお、結論を先にいうと開発者体験はとても良いです。
ビルド速度や使い始めの簡単さなど、一度はお試しをオススメします!

この記事を届けたい人

Docker Build Cloudを試してみたい人、ビルド環境を改善したい人

Docker Build Cloudとは

概略

Docker Build CloudはDocker社が提供するビルド環境です。
Dockerのコンテナライフサイクルのうちビルドはそれなりにコンピューティングリソースを使うため、そのリソースを提供してくれるクラウドサービスです。
Dockerのエコシステムに組み込まれているため、普段のDockerクライアントにオプションを追加する程度の手間で使い始められます。

コスト

先にまとめると、プランごとに使える時間などのリソースに制約がありますが、試用であれば無料で開始できます。

まず公式サイトの価格表を画像で引用します。

Docker Build Cloudのプラン表(2024/03/27時点)

Docker Build Cloud単体で使う場合はスターター/チーム/ビジネスのいずれかのサブスクリプションを購入します。
この中で具体的に金額が提示されているのはチームだけで、月額$6(年額だと月額$5相当)です。

ただ、Docker社はDockerを便利に使うためのアプリとしてDocker Desktopを公開しており、これが2021/09/01に有料化が公表されています。

www.publickey1.jp

このため一定規模以上の会社ではDocker Desktopを使用している場合はDocker Codeサブスクリプションに加入しています。
弊社もサブスクリプションをすでに購入しており、Docker Core Teamプランに加入済みでした。

www.docker.com

Docker Coreサブスクリプションに加入している場合はDocker Build Cloudの利用時間やディスク領域が割り当てられており、Docker Build Cloudを利用することができます。

Docker Coreサブスクリプションのプランと付与されるDocker Build Cloudのビルド時間など(2024/03/27時点)

つまりDocker Build CloudのサブスクリプションまたはDocker Coreサブスクリプションに加入することで、Docker Build Cloudを利用することがでるようです。
パーソナルでも50分/月のビルド時間と50GiBのキャッシュ領域が割り当てられているので、試用したり一部のプロダクトで使い始めるのは無料で試せると思います!

Docker Build Cloudを使う

Docker Build Cloudはビルド環境のクラウドなので、要は docker build . を実行する環境です。
Dockerはクライアント・サーバー型のアプリケーションなので、Dockerクライアントで実行したbuildコマンドはいずれかのサーバーで実行されます。
(大抵はクライアントと同じマシンにインストールされたサーバーでしょう)

このため、Docker Build Cloudを使うためにはビルドを実行するサーバーを明示して、認証を通すだけで良いです。
あとはクライアントが適切なサーバーにリクエストを送って処理をしてくれます。
簡単ですね。

以降で実際の手順を紹介します。

Docker Build Cloudのセットアップ

Docker Hubのアカウントを作成済みの前提で手順を書いていきます。

Docker Hubにログインして右上のタイル状のメニューアイコン(Bento Menuというらしいです)をクリックすると「Docker Build Cloud」というメニューがあります。

Docker HubからDocker Build Cloudに移動

クリックすると弊社の場合は個人アカウントか組織かどちらかを選択する画面になります。おそらくチームサブスクリプションだからでしょう。
どちらを選んでもメニューからアカウント/組織を変更できるのでどちらでもいいです。
今回は組織を選びます。

Docker Build Cloudのアカウント・組織選択画面

組織の画面のメニューで「Build Cloud」を選択すると、Builderの一覧とDocker Build Cloudの使用状況が表示されています。
最初はこのBuilderが存在しないと思います。

Build Cloudで使うBuilderの一覧画面

まずBuilderを作る必要がありますので適宜作成してください。
本当はここで丁寧に手順を説明したいのですが、Builderは組織で共用され、複数作る場合にはコンタクトをする必要があります。
すでに使っているBuilderを削除して手順をお見せするわけにはいかないので、ここは皆さんでお試しください…!
確か名前を設定するくらいだったと記憶しています。

複数のBuilderの作成は要コンタクト

作成したビルダーをクリックすると使い方の画面が表示されます。
この時点でDocker Build Cloudを使用してビルドする準備が整いました。

Builderの使用方法画面

組織の場合は「User Management」メニューからアカウントの招待ができます。
ここで招待されたアカウントがDocker Build Cloudを使用できるアカウントになります。

ユーザー管理画面から招待ができる

ちょうどスクリーンショットに記載がありますが招待に伴ってDocker Build Cloudの実行時間を貰えました。
最初はこれで色々遊んでみるといいと思います。

Docker Build Cloudをローカル環境でのビルドに使うには

上記のBuilderの詳細画面に全て書いてありますが、とても簡単です。

  1. dockerにログイン
  2. buildxでビルダーを作成
  3. ビルドコマンドを実行

これだけです。

まずログインします。

$ docker login
Authenticating with existing credentials...
Login Succeeded

次にビルダーを作成します。
ここではドライバーにcloudを指定し、名前にenechange/shared-cloud-builderを指定しています。
名前はORG/BUILDER_NAMEという規則で指定する必要があります。

$ docker buildx create --driver cloud enechange/shared-cloud-builder
cloud-enechange-shared-cloud-builder

$ docker buildx ls
NAME/NODE                            DRIVER/ENDPOINT                                    STATUS  BUILDKIT             PLATFORMS
cloud-enechange-shared-cloud-builder cloud
  linux-amd64                        cloud://enechange/shared-cloud-builder_linux-amd64 running v0.12.5              linux/amd64*, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
  linux-arm64                        cloud://enechange/shared-cloud-builder_linux-arm64 running v0.12.5              linux/arm64*, linux/arm64/v6, linux/arm64/v7
...

ローカル環境にビルダーが作られ、Docker Build Cloudを使う設定になりました。
ビルダーの名前は cloud-enechange-shared-cloud-builder になりました。cloud-ORG-BUILDER_NAMEという規則でしょうか。
あとはビルドコマンドを実行する際にビルダーを指定します。

$ docker buildx build --builder cloud-enechange-shared-cloud-builder .
[+] Building 0.0s (0/0)        cloud:cloud-enechange-shared-cloud-builder
WARNING: No output specified with cloud driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
...

これで普通にビルドが実行されます。
なお、ワーニングが出ている通り、outputが指定されていないとビルド結果はただBuilderのキャッシュに保存されるのみです。
リポジトリにプッシュする場合はpushオプションを、プッシュせずにイメージを使う場合はロードオプションが要るようです。

実際に使ってみると驚くほど簡単ですし、Teamサブスクリプションではビルド環境として16 vCPU、 32GB RAMの環境が使えているようです。
(以前は表で明示されていたのですが、今は問い合わせないとわからなさそうです)
十分強力なビルド環境ではないでしょうか。

ローカルのリソースを使うことなくクラウド上のビルド環境を簡単に(実質的にはログインするだけで)使えるので、大変お得ですね。
デフォルトのビルダーにしてしまえばオプションの指定も不要です。

$ docker buildx use cloud-enechange-shared-cloud-builder --global

Docker Build CloudをGitHub Actionsでのビルドに使うには

業務などでビルドを行う場合はCI環境を整備していることも多いでしょう。
一例としてGitHub Actionsでビルドをする際にDocker Build Cloudを使うパターンを紹介します。

といっても、基本的な手順はすでにBuilderの詳細画面に書いてあります。
Builderの詳細画面の「GitHub Actions」タブを選択すると以下のYAMLが表示されます。

name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: "lab:latest"
          driver: cloud
          endpoint: "enechange/shared-cloud-builder"
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          tags: "IMAGE"
          # For pull requests, export results to the build cache.
          # Otherwise, push to a registry.
          outputs: ${{ github.event_name == 'pull_request' && 'type=cacheonly' || 'type=registry,push=true' }}

基本的にはこれだけです。
やっていることは

  1. GitHub Actionsのランナーを準備
  2. リポジトリチェックアウト
  3. dockerにログイン
  4. buildxでビルダーを作成
  5. ビルドコマンドを実行

ですので、ローカルでやっていることと同じです。

詳細はdocker/build-push-action@v5のリポジトリに譲りますが、tagにリポジトリのドメインを入れておくことでoutputsオプションでイメージプッシュをする設定になっていればリポジトリに格納されます。
弊社の設定例だと以下のようになっています。

name: Docker image build
on:
  push:
    branches:
      - 'example'

jobs:
  build:
    name: Docker build
    runs-on: ubuntu-latest
    # These permissions are needed to interact with GitHub's OIDC Token endpoint.
    permissions:
      id-token: write
      contents: read
    steps:
      - name: checkout
        uses: actions/checkout@v3
        with:
          lfs: true
      # ECRにプッシュするためにAssume Role
      - name: Configure AWS credentials from IAM Role
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::999999999999:role/service-role/github-actions-service-role
          aws-region: ap-northeast-1
      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }} # GitHub Actionsのシークレットに設定したDocker Hubのユーザー名
          password: ${{ secrets.DOCKERHUB_TOKEN }} # GitHub Actionsのシークレットに設定したDocker HubのPAT(後述)
      - name: Log in to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: "lab:latest"
          driver: cloud
          endpoint: "enechange/shared-cloud-builder"
      - name: Prepare docker image tags
        shell: bash
        run: |
          SHORT_COMMIT_HASH=`git show --format='%h' --no-patch`
          ECR_REPOSITORY_URL=${{ vars.ECR_REPOSITORY_URL }} # GitHub Actionsの変数に設定したリポジトリURL
          echo "WEB_TAG=${ECR_REPOSITORY_URL}:web-${SHORT_COMMIT_HASH}" >> "$GITHUB_ENV"
      - name: Build web
        uses: docker/build-push-action@v5
        with:
          context: .
          build-args: |
            "RAILS_MASTER_KEY=${{ secrets.RAILS_MASTER_KEY }}"
            RAILS_ENV=production
          platforms: linux/arm64 # デプロイ環境に合わせたビルドプラットフォーム指定
          tags: ${{ env.WEB_TAG }}
          outputs: type=registry,push=true # ビルド後にPush
          provenance: false # デフォルトのマルチアーキテクチャビルドは不要のため抑制

ポイントを挙げるとすると以下の点でしょうか。どちらも嬉しいですね。

  • デフォルトでarm64とamd64のビルド環境が提供されているので、マルチアーキテクチャのビルドがplatformsオプションだけでできる
  • ログインとbuildxビルダーの設定をするだけであとは普通のビルドワークフローと変わりない

dockerログインに使うパスワードはPATを発行して使うとよいです。
Docker Hubにログインして右上の丸囲みのリンクから→My Account→左メニューのSecurity→New Access Tokenで作成できます。
トークンは一度しか表示されませんので管理はご注意ください。

DockerのPAT作成画面

トークンのScopeはRead-onlyで十分です。

AWS CodePipelineにDocker Build Cloudでのビルドを組み込むには

業務上ではCI環境だけではなくCD環境としてパイプラインを構築していることも多いかと思います。
弊社の場合はAWS CodePipelineでビルド&デプロイパイプラインを構築しています。
GitHubの特定ブランチへのPushをトリガにCodePipelineを起動し、CodeBuildでイメージをビルドしてECRにプッシュし、CodeDeployでECSへデプロイします。

AWS内でビルド〜デプロイを完結するパイプライン

今回はビルドをGitHub Actions(Docker Build Cloud)で行い、GitHub ActionsでデプロイをトリガするようにすることでワークフローにDocker Build Cloudを組み込みます。

具体的には以下のような構成にします。

  1. GitHub ActionsでIAM Roleをassume
  2. GitHub ActionsでDocker Build Cloudを呼び出してイメージをビルドしてECRにプッシュ
  3. GitHub ActionsでECSタスクデプロイに必要なファイル(taskdef.json, appspec.yml)を作成し、ZIPファイルにまとめてS3にPUT
  4. S3 PUTイベントでEventBridgeをトリガーし、EventBridgeからCodePipelineをトリガー
  5. CodeDeployがZIPファイルを取得し、ファイル内の内容に従ってECSへデプロイ

GitHub ActionsとAWSでビルドとデプロイを分担するパイプライン

登場人物が増えたので順を追って説明します。

GitHub ActionsがAssumeするRole

以下のような定義です。

信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::999999999999:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:<GitHub org name>/<GitHub repo name>:*"
                }
            }
        }
    ]
}

ポリシー

{
    "Statement": [
        {
            "Action": [
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:CompleteLayerUpload",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage",
                "ecr:UploadLayerPart"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ecr:ap-northeast-1:999999999999:repository/<ECR repository name>"
            ]
        },
        {
            "Action": "ecr:GetAuthorizationToken",
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": [
                "ecs:DescribeTaskDefinition"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": [
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::<bucket name>/*"
            ]
        }
    ],
    "Version": "2012-10-17"
}

特定のECRリポジトリの操作と特定S3バケットへのファイルPUTのみ許容すれば十分です。

Docker Build Cloudでビルド&ECRへプッシュ

前述のYAMLのとおりです。
特別なことはありませんが、後述する処理のためイメージに付与したタグはGitHub Actionsランナーの環境変数などで別stepから参照できるようにしておきましょう。

GitHub Actionsでデプロイに必要なファイルを作成してS3にPUT

後続のデプロイに必要なファイルを作成します。
ここではtaskdef.jsonappspec.ymlを作成し、1つのZIPファイルapplication.zipに纏めます。

AWS CodePipelineからECSをターゲットにしたAWS CodeDeployを呼び出す場合、入力アーティファクトとしてtaskdef.jsonappspec.ymlを渡してタスク定義のリビジョン追加とそのリビジョンのデプロイを行えます。

docs.aws.amazon.com

また、ZIP形式でまとめたファイルをS3にアップロードし、当該ファイルを入力アーティファクトに指定すると、受け取る側のCodeDeployには自動で展開された状態で引き渡されます。
便利ですね。

docs.aws.amazon.com

これらの機能を使うためにtaskdef.jsonappspec.ymlの作成後にZIPファイルに集約します。

また、taskdef.json内にはECRにデプロイするイメージとタグを指定する箇所があります。
ここで今回ビルドしたイメージを作成したいので、前述の通りビルド時に設定したタグをtaskdef.json内で指定する必要があります。

{
    "taskDefinitionArn": "...",
    "containerDefinitions": [
        {
            "name": "...",
            "image": "999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR repo name>:<tag>",
...

EventBridgeを介したS3 PUT→CodeDeployトリガー

S3バケットへのPUTをCodePipelineのSourceアクションのトリガーにする場合、現在はこの方法が推奨です。

docs.aws.amazon.com

作成するリソースの概略をTerraformで説明すると以下のとおりです。

CodePipeline

resource "aws_codepipeline" "deploy_only" {
  ...

  stage {
    name = "Source"

    action {
      category      = "Source"
      configuration = {
        "PollForSourceChanges" = "false"
        "S3Bucket"             = aws_s3_bucket.pipeline_app_source.bucket # aws_s3_bucket.pipeline_app_sourceは別途定義
        "S3ObjectKey"          = "application.zip"
      }
      input_artifacts  = []
      name             = "Source"
      namespace        = "SourceVariables"
      output_artifacts = [
        "SourceArtifact",
      ]
      owner     = "AWS"
      provider  = "S3"
      region    = "ap-northeast-1"
      run_order = 1
      version   = "1"
    }
  }
  stage {
    name = "Deploy"

    action {
      category      = "Deploy"
      ...
  }
}

EventBridge

resource "aws_cloudwatch_event_rule" "this" {
  name        = "app-source"
  description = "Capture app source created on S3 bucket"

  event_pattern = jsonencode({
    "source" : ["aws.s3"],
    "detail-type" : ["Object Created"],
    "detail" : {
      "bucket" : {
        "name" : [
          aws_s3_bucket.pipeline_app_source.bucket, # aws_s3_bucket.pipeline_app_sourceは別途定義
        ]
      },
      "object" : {
        "key" : ["application.zip"]
      }
    }
  })
}

resource "aws_cloudwatch_event_target" "this" {
  arn      = aws_codepipeline.this.arn
  rule     = aws_cloudwatch_event_rule.this.name
  role_arn = aws_iam_role.eventbridge
}

EventBridgeのRole

{
    "Statement": [
        {
            "Action": [
                "codepipeline:StartPipelineExecution"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:codepipeline:ap-northeast-1:999999999999:<CodePipeline pipeline name>"
            ]
        }
    ],
    "Version": "2012-10-17"
}

EventBridgeのRoleの信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

なお、application.zipをPUTする先のS3バケットはバージョニングを有効化する必要があります(制約)。

これらを作成することで、指定のS3バケットにapplication.zipというファイルが配置されたことをトリガーにCodePipelineを発火できます。
CodePipelineのSourceステージではS3をソースにしますが、ファイルのポーリングは行わず発火はEventBridgeに任せる形です。

CodeDeployによるECSへのデプロイ

ここは元々のパイプラインと変わりありません。

使ってみての感想

ローカルやGitHub Actionsで使う場合、大変手軽に使用できるというメリットを感じました。
簡単に使えるというのは実に嬉しくて、Dockerが元からクライアント・サーバー型であることで実行環境が抽象化されている嬉しさが出ていると思います。

また、基本的に「ただビルドを行う環境を提供されているだけ」であるので、単純なビルド速度改善がそのまま効きます。
これはとても嬉しいです!
今までのCI環境の速度改善は何らかのCI環境特有の改善が必要なことが多かったと思いますが、Docker Build Cloudであれば単純にローカル同様のDockerfileの改善がそのままCI性能改善になります。
ここはとても嬉しいので(二回目)以降でも紹介します。

弊社では恩恵が少なかったですが、マルチプラットフォームなビルド環境が最初から提供されているのも嬉しそうです。

元々Docker Coreサブスクリプションを購入している場合は追加コスト無しで使い始められる準備の整ったビルド環境が提供されるので、ぜひ使ってみると良いと思います。

Docker Build Cloudと他ビルド環境との比較

業務のCI環境としてDocker Build Cloudを使う場合を想定し、他のビルド環境と比較してみます。
コスト面の比較は使用時間コストとサブスクリプションコストがあるため難しいので性能面や使い勝手の比較をします。
また、前提としてDocker Build Cloudはチームサブスクリプションです。

GitHub Actionsのランナーでのビルドと比較

GitHub Actionsのランナーでそのままビルドを行っている場合と比較します。

  • 実行環境
  • ビルド時間
    • キャッシュ面でDocker Build Cloudが有利です
    • GitHub ActionsでDockerレイヤーキャッシュやBuildxマウントキャッシュを使う場合はactions/cacheを使うのがデファクトスタンダードですが、これはリポジトリ単位のキャッシュです。
      Docker Build CloudはBuilderで共通のキャッシュのようですので、node_modulesなどのダウンロードするライブラリのマウントキャッシュがより効きやすいでしょう。
      業務であれば複数のGitHubリポジトリでビルドを行っていることもあると思いますので共用のキャッシュはより価値がでそうです。
      加えてキャッシュ容量もGitHub Actions(10GB) < Docker Build Cloud(50GB〜200GB)です。
    • ただし現時点でDocker Build Cloudは北米にしか実行環境がありませんので、ビルドコンテキストの転送にはやや時間がかかる印象があります
  • 使い勝手
    • ワークフローのYAMLに書くべき内容はほぼ差がないです
    • 実行環境依存の部分はDocker Build Cloudがとても使いやすいです。
      Docker Build Cloudはamd64/arm64が同時に提供されるので、ビルドイメージ毎にランナーを変えたりQEMUを設定したりする必要がありません。

それぞれメリットがありますが、Docker Build Cloudは使い勝手とキャッシュの面でやや良さそうです。
またGitHub Actionsはより大きなランナーを使うと時間あたりのコストが上昇していきます。 何らかのDocker Coreサブスクリプションを購入済であれば追加コスト無しで性能向上が見込めるのでDocker Build Cloudを使うのはオススメです。

AWS CodeBuildでのビルドと比較

AWS CodeBuildでビルドを行った場合と比較します。
CodeBuildでDockerイメージのビルドを行う場合はAWS Lambdaを実行環境にできませんので、EC2コンピューティング環境を対象に比較します。

  • 実行環境
    • CodeBuildのビルド環境イメージやリザーブドキャパシティーの仕様有無によって変わります。
      • aarch64をビルド環境イメージにする場合
        CodeBuild(8vCPU 16GB RAM) <= Docker Build Cloud(8vCPU 16GB RAM 〜 16vCPU 32GB RAM)です。
      • x86_64をビルド環境イメージにする場合
        CodeBuild(2vCPU 3GB RAM 〜 72vCPU 145GB RAM)は幅広く、 Docker Build Cloud(8vCPU 16GB RAM 〜 16vCPU 32GB RAM)はその中間です。
      • リザーブドキャパシティーを使う場合
        CodeBuild(2vCPU 3GB RAM 〜 72vCPU 145GB RAM)は幅広く、 Docker Build Cloud(8vCPU 16GB RAM 〜 16vCPU 32GB RAM)はその中間です。
  • ビルド時間
    • キャッシュの面でDocker Build Cloudが有利でしょう。
      CodeBuildでビルド環境のEC2インスタンスをたまたま使い回すことができた場合(大抵は短時間で複数回同じビルドプロジェクトを実行した場合)を除くと、CodeBuildでは何もせずにキャッシュが効くことはありません。
      CodeBuildのS3キャッシュを利用するとBuildxのマウントキャッシュを効かせられますがDockerレイヤーキャッシュには効かないようです。
      Docker Build Cloudは単純にビルド実行環境の提供なので、何もせずにDockerレイヤーキャッシュとBuildxマウントキャッシュが効きます。
    • プロビジョニング時間の点でDocker Build Cloudが有利です。
      ここ最近はそうでもないですが、CodeBuildはプロビジョニングに時間がかかることが多かったです。
      場合によってはプロビジョニングだけで60秒かかることもありました。
      Docker Build Cloudは今のところプロビジョニングにそれほど時間はかかりません。
  • 使い勝手
    • Docker Build Cloudが有利です。
      ワークフローYAML(buildspec.yml.github/workflows/xxx.yml)の差はさほどないですが、前述の通りキャッシュ周りの使い勝手はDocker Build Cloudが抜群に良いです。
      特段別リソースを用意することなくキャッシュが効き、キャッシュ改善は単純なDockerfileの改善=ローカルビルド速度の改善と同様の作業だけで済みます。
    • CIだけであればリポジトリへのPUSHをIAMで許可してビルドサービスであるCodeBuildまたはGitHub Actionsにassumeさせることは同じなので、ほぼ差はないです。
      ただしCDパイプラインをAWSのサービスで構築し、そことの連携でいうとCodeBuildの方が簡便でしょう。
      Docker Build Cloudは連携のためにそれなりにリソースや設定が必要になります。
    • Docker Build Cloudではマルチプラットフォームビルドも特段の準備がいりませんのでこちらも大変使いやすいでしょう

実行環境の性能についてはGitHub Actionsのランナー同様「どれだけコストをかけるか」次第になります。
専有環境にせよより大きなインスタンスにせよ起動時間に比例したコストがかかるため、こちらもDocker Coreサブスクリプションを購入済みであればDocker Build Cloudはオススメです。

また、ビルド速度の向上に他のリソースを必要としない点はDocker Build Cloudの大きなメリットです。
Dockerfileのプラクティスがそのままビルド速度の改善になるため、開発者には嬉しいでしょう。

なお、弊社の場合はARMプラットフォームのイメージビルドをCodeBuildからDocker Build Cloudに変更しただけで以下のような速度改善が得られました。

  • 初回ビルド
    • 474s(CodeBuild)→337s(Docker Build Cloud)
    • -137s(ー29%)
  • 二回目以降
    • 474s(CodeBuild)→47s(Docker Build Cloud)
    • -427s(ー90% !!!)

二回目以降はDockerレイヤーキャッシュがフルに効いてくれているおかげで相当なビルド時間短縮になっています。

比較しての感想

コスト面と手軽さがDocker Build Cloudの大きな強みだと感じました。

コスト面においてはDocker Coreサブスクリプションを購入済みであれば追加コスト無しで比較的性能の良いビルド環境が提供されます。 「Docker Coreサブスクリプションが購入済み」というのも特殊条件ではなく、業務でDockerを使っている場合は大抵何らかのサブスクリプションを購入($0のものも含めて)していると思います。
他のビルド環境と比べて「CIのために追加コストが発生する」ということはないと思います。

手軽さにおいてはただDockerfileを改善するとCI速度が改善するというメリットは強力です。
キャッシュ周りの環境整備やキャッシュの共用について何も検討・構築せずに、ただローカル環境でビルドを早くするのと同じ方法でCI速度を改善できます!
そもそもローカルのビルド環境も簡単にDocker Build Cloudに移行できるので、CI速度改善の試行錯誤をそのままDocker Build Cloud上で行えます。
ビルド速度向上はインフラチームとの共同作業ではなく、アプリチーム単体で進められることになる点もメリットが有るのではないでしょうか。

ただしビルド環境を金の弾丸で性能モリモリにしたい!…といった場合の選択肢は既存のビルド環境に軍配が上がります。
最初から選択肢としてビルド環境の性能が複数提示されているので簡単に効用が得られるでしょう。

まとめ

Docker社が提供するDocker Build Cloudについて使用方法やCI/CDパイプラインへの組み込み、他のビルド環境との比較を行いました。
Dockerをすでに利用している方にはとてもオススメのサービスです!
お試しで使ってみるプランならコストは掛かりません!!
ぜひ皆さん触ってみましょう!!!