一覧に戻る
    AIが提案したプランをリジェクトして、ECR認証の方針を考えた話
    開発ラボ
    PRこの記事には広告が含まれています

    AIが提案したプランをリジェクトして、ECR認証の方針を考えた話

    11 分で読める

    JenkinsパイプラインのエージェントとしてECRのプリビルドイメージを使いたい。

    動機はシンプルで、毎回 docker build を走らせるのをやめて、ビルド済みイメージをそのまま引っ張ってくることでパイプラインを速くしたかった。

    で、Claude Codeにプランを立てさせたら、「こうするといいですよ」と出てきた案が思ったより複雑で。

    リジェクトしました。

    最初に提案されたプラン

    Jenkinsfileは今こういう構造になっている。

    pipeline {
        agent {
            dockerfile {
                label 'ec2-fleet-small'
                dir '.'
                filename 'Dockerfile'
                args "-v \${WORKSPACE}:/workspace -w /workspace"
            }
        }
        stages { ... }
        post { /* archiveArtifacts, cleanWs, webhook */ }
    }

    これをECRイメージに切り替えるにあたって、AIが提案してきたのはこういう構造だった。

    pipeline {
        agent { label 'ec2-fleet-small' }  // まずベアホスト
        stages {
            stage('ECR Login') { ... }     // ここでECR認証
            stage('Run in Docker') {
                agent { docker { image ECRイメージ, reuseNode true } }
                stages { 既存の全ステージ }
                post { archiveArtifacts, クリーンアップ }
            }
        }
        post { cleanWs, webhook }
    }

    狙いはわかる。ECR Loginをベアホストで走らせて、その認証情報を使ってDockerエージェントを立ち上げる。reuseNode true で同じノードを再利用するから、ログイン済みの状態が引き継がれる。

    post ブロックの分割理由も筋が通っていた。Dockerコンテナ内の /tmp/ にあるファイルにアクセスする必要があるステップは、コンテナが死ぬ前にDockerステージの post でやる必要がある。cleanWsとwebhookはパイプラインレベルの post に残す——という設計。

    ただ、パイプライン全体の構造を変えないといけない。ネストされたステージ、postブロックの分割、スクリプトスコープの変数管理……。

    やりたいことに対して、変更量が多すぎる気がした。

    「もっと楽なやり方、あるんじゃない?」

    リジェクトして聞いてみた。

    すると二つの選択肢が出てきた。

    案1: amazon-ecr-credential-helper(EC2 OSレベル)

    案2: Jenkins の Amazon ECR プラグイン(Jenkins側)

    二つのアプローチを比較した

    どちらも「DockerがECRから自動でイメージをpullできるようにする」という目的は同じ。ただ、仕組みと設置場所が違う。

    credential-helperJenkins ECR プラグイン
    設置場所EC2インスタンス(OSレベル)Jenkins(プラグイン)
    認証方式IAMインスタンスプロファイルJenkinsのCredentials
    Jenkinsfile変更agent ブロックだけregistryUrl + credentialsId を追加
    影響範囲そのインスタンス上の全Docker該当ジョブのみ
    他ジョブへの展開Jenkinsfile変更不要各ファイルに記述が必要
    EC2の変更AMI/ユーザーデータに追加不要

    Jenkinsfileの変更量で言えば、credential-helperの方が断然少ない。

    // ECR プラグインを使う場合
    agent {
        docker {
            image '<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/your-image:latest'
            registryUrl 'https://<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/'
            registryCredentialsId 'ecr:ap-northeast-1:<Jenkins Credential ID>'
            label 'ec2-fleet-small'
        }
    }
    
    // credential-helper を使う場合
    agent {
        docker {
            image '<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/your-image:latest'
            label 'ec2-fleet-small'
            alwaysPull true
        }
    }

    credential-helperが入っていれば、Jenkinsfileには認証に関する記述が一切不要になる。EC2のIAMインスタンスプロファイルを使って、Dockerが自動でECR認証してくれるから。

    credential-helper を選んだ理由

    credential-helperに決めた。

    理由は大きく二つ。

    今後の展開を考えると、各Jenkinsfileに認証情報を書きたくない。

    今回対象のジョブだけじゃなく、他のパイプラインも順次ECRイメージに切り替えていく予定がある。ECRプラグインだと、そのたびに registryUrlregistryCredentialsId をJenkinsfileに追記しないといけない。credential-helperが入っていれば、全ジョブで何も書かなくていい。

    Docker Hub など他のレジストリへの影響がない。

    これは最初に確認した。credential-helperは credHelpers という仕組みで動いていて、ドメイン単位で設定する形になっている。

    {
      "credHelpers": {
        "<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com": "ecr-login"
      }
    }

    ここに書かれていないレジストリには一切干渉しない。Docker Hubからのpullは今まで通り動く。

    トレードオフとして、EC2のAMIかユーザーデータに手を入れる必要がある。インフラレイヤーの変更だから、Jenkinsfileの変更より影響範囲は広い。ただ「一度入れれば全部に効く」という性質上、許容できるコストだと判断した。

    なので、まずインフラレイヤーから

    ここで気づいたのが、順番の問題だった。

    credential-helperがEC2インスタンスに入っていない状態で、JenkinsfileをECRイメージに切り替えても当然動かない。前提条件が満たされていない。

    必要なのは:

    1. EC2フリートインスタンスに amazon-ecr-credential-helper をインストール
    2. Dockerを実行するユーザーの ~/.docker/config.jsoncredHelpers を設定
    3. EC2のIAMロールに必要なECR権限を確認(ecr:GetAuthorizationTokenecr:BatchGetImageecr:GetDownloadUrlForLayer

    これはJenkinsfileではなく、インフラのコードを変更する話になる。

    なのでJenkinsfileを先に触るのではなく、まずIaCのIssueを起票してインフラ側の更新を先に進めることにした。インフラが整ったら、Jenkinsfileの変更はagentブロックを数行書き換えるだけで済む。

    現時点での状態

    まだJenkinsfileの変更はしていない。

    インフラ側のIssueを作って、そちらを先に対応する順番にした。変更が終わったら、改めてJenkinsfileのPRを出す予定。

    途中までの判断をメモとして残しておく。

    参考リソース

    Jenkinsのパイプライン設計やAWSインフラの運用について、以下の書籍が参考になります。

    この記事は役に立ちましたか?

    Coffee cup

    この記事が、何かの整理につながったら

    コーヒー1杯分の応援をもらえると嬉しいです。

    ※ これは応援とは別の話ですが、

    同じようなテーマを自分の文脈で整理したい場合は、 (文章だけだと詰まりやすい人向けに) 思考整理の壁打ちという形で対話の時間も取っています。

    対話の時間について