I wanted to use an ECR prebuilt image as a Jenkins pipeline agent. The motivation was simple — stop running docker build every time and just pull a pre-built image to speed up the pipeline.
So I had Claude Code draft a plan, and the proposal that came back was more complex than I expected.
I rejected it.
The Initial Proposal
The current Jenkinsfile has this structure:
pipeline {
agent {
dockerfile {
label 'ec2-fleet-small'
dir '.'
filename 'Dockerfile'
args "-v \${WORKSPACE}:/workspace -w /workspace"
}
}
stages { ... }
post { /* archiveArtifacts, cleanWs, webhook */ }
}
To switch this to an ECR image, the AI proposed the following structure:
pipeline {
agent { label 'ec2-fleet-small' } // bare host first
stages {
stage('ECR Login') { ... } // authenticate here
stage('Run in Docker') {
agent { docker { image ECR_IMAGE, reuseNode true } }
stages { all existing stages }
post { archiveArtifacts, cleanup }
}
}
post { cleanWs, webhook }
}
The reasoning made sense. Run the ECR Login on the bare host, then use those credentials to launch the Docker agent. With reuseNode true, the same node is reused, so the authenticated state carries over.
The split post blocks were logical too. Steps that need access to files in the Docker container's /tmp/ must run in the Docker stage's post before the container dies. cleanWs and the webhook stay in the pipeline-level post.
But it required restructuring the entire pipeline — nested stages, split post blocks, script-scoped variable management...
The amount of change felt disproportionate to what I was trying to achieve.
"Isn't There an Easier Way?"
I rejected the plan and asked.
Two alternatives came up:
Option 1: amazon-ecr-credential-helper (EC2 OS level)
Option 2: Jenkins Amazon ECR Plugin (Jenkins side)
Comparing the Two Approaches
Both aim to let Docker automatically pull images from ECR. The difference is in the mechanism and where it's configured.
| credential-helper | Jenkins ECR Plugin | |
|---|---|---|
| Where it lives | EC2 instance (OS level) | Jenkins (plugin) |
| Auth method | IAM instance profile | Jenkins Credentials |
| Jenkinsfile changes | agent block only | registryUrl + credentialsId |
| Scope | All Docker on instance | Target job only |
| Scaling to other jobs | No Jenkinsfile changes | Must add to each file |
| EC2 changes needed | AMI/user data update | None |
In terms of Jenkinsfile changes, credential-helper wins by a wide margin.
// Using the ECR Plugin
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'
}
}
// Using credential-helper
agent {
docker {
image '<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/your-image:latest'
label 'ec2-fleet-small'
alwaysPull true
}
}
With credential-helper installed, the Jenkinsfile needs zero authentication configuration. Docker handles ECR auth automatically using the EC2's IAM instance profile.
Why I Chose credential-helper
I went with credential-helper for two main reasons.
I don't want authentication config scattered across Jenkinsfiles.
This isn't just about one job. Other pipelines will be switching to ECR images too. With the ECR plugin, every Jenkinsfile would need registryUrl and registryCredentialsId added. With credential-helper, none of them need anything.
No impact on other registries like Docker Hub.
I checked this first. credential-helper uses a credHelpers mechanism that works on a per-domain basis:
{
"credHelpers": {
"<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com": "ecr-login"
}
}
It doesn't touch any registry not listed here. Docker Hub pulls continue to work as before.
The trade-off is that the EC2 AMI or user data needs to be updated. It's an infrastructure-layer change, so the blast radius is wider than a Jenkinsfile change. But given that it's a one-time setup that benefits all jobs, I judged it an acceptable cost.
So, Infrastructure First
This is where I realized the sequencing matters.
If credential-helper isn't installed on the EC2 instances, switching the Jenkinsfile to an ECR image simply won't work. The prerequisite isn't met.
What's needed:
- Install
amazon-ecr-credential-helperon EC2 fleet instances - Configure
credHelpersin~/.docker/config.jsonfor the Docker user - Verify the EC2 IAM role has the required ECR permissions (
ecr:GetAuthorizationToken,ecr:BatchGetImage,ecr:GetDownloadUrlForLayer)
This is an infrastructure code change, not a Jenkinsfile change.
So rather than touching the Jenkinsfile first, I filed an IaC issue to update the infrastructure. Once that's done, the Jenkinsfile change is just a few lines in the agent block.
Current Status
The Jenkinsfile hasn't been changed yet.
I created the infrastructure issue and prioritized that work first. Once it's done, I'll submit the Jenkinsfile PR.
Documenting the decision process here while it's still fresh.
Recommended Resources
The following books are helpful for understanding Jenkins pipeline design and AWS infrastructure operations.
[📦 商品リンク: moshimo-book-jenkins-jissen]
[📦 商品リンク: moshimo-book-jenkins-blue]
[📦 商品リンク: moshimo-book-aws-operations]