5

The situation here is that we have an app that's currently being built on a Jenkins slave with a certain version of node installed on it. We want to standardize the build environment, and so to do that want to build inside a docker container.

Through my research it definitely seems possible. However, the challenge for us is we want to use custom images we manage ourselves and store in ECR. We don't want to use the ones on docker hub. With that constraint in mind, I'm struggling to authenticate into our ECR within my Jenkinsfile. Ideally I could do something like this:

pipeline {
    agent {
        docker {
            image 'node:7'
            registryUrl 'ecr_url.amazonaws.com'
            registryCredentialsId 'ecr:us-east-1:iam_role'
        }
    }
    stages {
        stage('Build') {
            steps {
                sh 'command goes here'
            }
        }
    }
}

But the issue here is that our ECR login relies on running a shell command on the Jenkins worker (which has aws cli installed) to log in and access the image. So far I've had no luck authenticating within the Jenkinsfile so I can pull an image to run the build in. Does anyone know if this is possible and if so, how to edit the Jenkinsfile to do it?

Answorth
  • 147
  • 1
  • 2
  • 10
  • Let me see if I understand you; if an image called: stackoverflow/votes-engine exist in the public docker hub and you have created answorth/votes-engine in your ECR, Do you want to use your **votes-engine** instead public using just **FROM votes-engine** ? – JRichardsz Oct 30 '19 at 01:17
  • Yeah that's right. We have our own images (answorth/votes-engine) which we want to pull and build the app in per the instructions in the rest of the container. The challenge is logging into our ECR via the Jenkinsfile. – Answorth Oct 30 '19 at 01:21
  • @Adiii answer helps you? – JRichardsz Oct 30 '19 at 15:04

3 Answers3

2

You need Authorization token before pulling the image from ECR it's mean you also need to install AWS-CLI on Jenkins server. The best approach is to assign role and run the below command somewhere in your pipeline to get authorization token, if that seems complicated to you you can use ECR plugin below.

Your Docker client must authenticate to Amazon ECR registries as an AWS user before it can push and pull images. The AWS CLI get-login command provides you with authentication credentials to pass to Docker. For more information, see Registry Authentication.

AmazonECR-registry_auth

So you can use JENKINS/Amazon+ECR enter image description here

Amazon ECR plugin implements a Docker Token producer to convert Amazon credentials to Jenkins’ API used by (mostly) all Docker-related plugins. Thank's to this producer, you can select your existing registered Amazon credentials for various Docker operations in Jenkins, for sample using CloudBees Docker Build and Publish plugin:

Normally we use this command to obtain token.

$(aws ecr get-login --no-include-email --region us-west-2)

with in pipline you can try

pipeline
{
    options
    {
        buildDiscarder(logRotator(numToKeepStr: '3'))
    }

    agent any
    environment 
    {
        PROJECT = 'tap_sample'
        ECRURL = 'http://999999999999.dkr.ecr.eu-central-1.amazonaws.com'
        ECRCRED = 'ecr:eu-central-1:tap_ecr'
    }
    stages
    {
        stage('Docker image pull')
        {
            steps
            {
                script
                {
                    sh("eval \$(aws ecr get-login --no-include-email | sed 's|https://||')")
                    docker.withRegistry(ECRURL, ECRCRED)
                    {
                        docker.image(PROJECT).pull()
                    }
                }
            }
        }
    }
}
Adiii
  • 54,482
  • 7
  • 145
  • 148
  • Hi Adiii, yes this is helpful. I guess my outstanding question is how to use this in a declarative Jenkinsfile; all of our builds and pipelines now aren't configured directly in Jenkins, but in the Jenkinsfiles in source control. From your link about the amazon ecr plugin (which is installed for us) they have an example of how it could look with another pllugin? (the cloudbees docker pipeline) However, it uses the example of "ecr:us-east-1:credential-id" to login to ECR. How would we obtain this token if we're not running a shell command but just running the Jenkinsfule when we build? – Answorth Oct 30 '19 at 16:56
  • I assume it will create token automatically based on AWS registery or you can run in jenkins file this command before pull `$(aws ecr get-login --no-include-email --region us-west-2)` – Adiii Oct 30 '19 at 17:14
  • With the AWS CLI V2, the `get-login` command is deprecated and replaced with `get-login-password` instead. The new pattern would be `aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com` as shown at https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-authenticate-registry – Shawn Feb 17 '21 at 23:48
1

You almost had it working. The trick to using it as an agent on the declarative pipeline is to create an AWS credential with empty Access_key and Secret but setting an IAM role on it. Jenkins credential

pipeline {
    agent {
        docker { 
          image '<account-id>.dkr.ecr.eu-west-1.amazonaws.com/image/my-image:v1'
          args '--entrypoint= '
          registryCredentialsId "ecr:eu-west-1:aws-instance-role"
          registryUrl "https://<account-id>.dkr.ecr.eu-west-1.amazonaws.com"
        }
    }
    stages {
        stage('Test') {
            steps {
                sh "I'm on an ECR agent"
            }
        }
    }
}

Make sure that you can assume this role, you can an instance role that allows assuming itself. I've created a medium post describing this process on a cross-account ECR How to run Jenkins agents with cross-account ECR images using instance roles on EKS.

  • This is interesting, but I'm having trouble figuring out where/how you came up with the string "ecr:eu-west-1:aws-instance-role" used by the registryCredentialsId. Can you elaborate on that? – BigTexasDork May 22 '21 at 03:47
  • 1
    @BigTexasDork the string starts with "ecr:" to trigger the use of the amazon emr jenkins plugin for auth. Then the region. Then the ID. Here the ID is the ID of the Amazon Credential in the Credential store. "ecr" + : + AWS_REGION_NAME + : + CREDENTIAL_ID. Does that help? – spazm Jun 24 '21 at 07:47
0

use aws pipeline steps. It allows for a ecrLogin() where you can specify registry ids if needed. https://plugins.jenkins.io/pipeline-aws/#plugin-content-ecrlogin