Creating an ECR repository to manage our Docker image

In the first part of the chapter, we used the Docker Hub public registry. AWS provides a similar service called ECR, which will let you keep your images in a private registry called a repository. ECR is fully compatible with the Docker CLI, but also integrates deeply with the rest of the ECS services. We are going to use it to store our helloworld images.

As mentioned, we will heavily rely on CloudFormation to make our changes. Unlike what we saw previously, because of its nature, the ECS infrastructure we are going to build needs to be very modular as, in practice, we will want to share some of those components with other services. Therefore, we will create a number of templates and link them to one another. One good way to do that is to rely on CloudFormation's export ability, which lets us do cross-stack referencing.

One of the added bonuses that export provides is a fail-safe mechanism. You can't delete or edit a stack if another stack references an exported output.

We will create a new troposphere script to generate our template. Go to the EffectiveDevOpsTemplates repository and create a new ecr-repository-cf-template.py script.

We will start with the import of a number of modules, including the Export mentioned earlier, and the ecr module to create our repository. We will also create our template variable t as we did in the previous chapters:

"""Generating CloudFormation template.""" 
 
from troposphere import ( 
    Export, 
    Join, 
    Output, 
    Parameter, 
    Ref, 
    Template 
) 
from troposphere.ecr import Repository 
 
t = Template() 

Since we are going to create a number of CloudFormation templates in this chapter, we will add a description so that it's easier to understand which template does what when looking at them in the AWS console:

t.add_description("Effective DevOps in AWS: ECR Repository") 

We will create a parameter for the name of the repository so that we will be able to reuse that CloudFormation template for every repository we create:

t.add_parameter(Parameter( 
    "RepoName", 
    Type="String", 
    Description="Name of the ECR repository to create" 
)) 

We can now create our repository as follows:

 t.add_resource(Repository( 
    "Repository", 
    RepositoryName=Ref("RepoName") 
)) 

We are keeping the code very simple here and not enforcing any particular permissions. If you need to restrict who can access your repository, and to see more complex configurations, you can refer to the AWS documentation and, in particular, http://amzn.to/2j7hA2P.

Lastly, we will output the name of the repository we created and export its value through a template variable:

t.add_output(Output( 
    "Repository", 
    Description="ECR repository", 
    Value=Ref("RepoName"), 
    Export=Export(Join("-", [Ref("RepoName"), "repo"])), 
)) 
 
print(t.to_json()) 

We can save our script and it should look like this: http://bit.ly/2w2p2D5.

We will now generate the CloudFormation template and create our stack as follows:

$ python ecr-repository-cf-template.py > ecr-repository-cf.template
$ aws cloudformation create-stack
--stack-name helloworld-ecr
--capabilities CAPABILITY_IAM
--template-body file://ecr-repository-cf.template
--parameters
ParameterKey=RepoName,ParameterValue=helloworld

After a few minutes, our stack will be created. We can validate that the repository was correctly created:

$ aws ecr describe-repositories
{
"repositories": [
{
"registryId": "511912822958",
"repositoryName": "helloworld",
"repositoryArn": "arn:aws:ecr:us-east-1:511912822958:repository/helloworld",
"createdAt": 1484252219.0,
"repositoryUri": "511912822958.dkr.ecr.us-east-1.amazonaws.com/helloworld"
}
]
}

We can see our exported output with the following command:

$ aws cloudformation list-exports
{
"Exports": [
{
"ExportingStackId": "arn:aws:cloudformation:us-east-1:511912822958:stack/helloworld-ecr/01473e10-e1c2-11e6-8a73-500c219b8099",
"Value": "helloworld",
"Name": "helloworld-repo"
}
]
}

Our repository can now be used to store our helloworld image. We will use the Docker CLI to do that. The first step of that process is to log in to the ecr service. You can do it with the following handy one-liner:

$ eval "$(aws ecr get-login --region us-east-1 --no-include-email )"

Back in our helloworld directory, where the Dockerfile is, we will tag our image:

$ cd helloworld

It is a common practice to use the tag latest to designate the most recent version of an image. In addition, you need to adapt the following command based on the output of the aws ecr describe-repositories output (we assume here that you have already built your image):

$ docker tag helloworld:latest 511912822958.dkr.ecr.us-east-1.amazonaws.com/helloworld:latest

We can now push that image to our registry:

$ docker push 511912822958.dkr.ecr.us-east-1.amazonaws.com/helloworld:latest
The push refers to a repository [511912822958.dkr.ecr.us-east-1.amazonaws.com/helloworld]
105cbf48989e: Pushed
07063be54b8f: Pushed
91cb8cc7a37f: Pushed
520e3b31bf3e: Pushed
7cbcbac42c44: Pushed
latest: digest: sha256:0e2ab02729d9f075abf79bb3a63dab90e2a4ce4f196a1ee8369edb95ba788e20 size: 1361

We can see how each layer of our image is pushed in parallel to our registry.

Once the operation completes, we can validate that the new image is present in our registry:

$ aws ecr describe-images --repository-name helloworld
{
"imageDetails": [
{
"imageSizeInBytes": 13071647,
"imageDigest":
"sha256:0e2ab02729d9f075abf79bb3a63dab90e2a4ce4f196a1ee8369edb95ba788e20",
"imageTags": [
"latest"
],
"registryId": "511912822958",
"repositoryName": "helloworld",
"imagePushedAt": 1485551754.0
}
]
}

At this point, our image is now available to the rest of our infrastructure. We are going to move on to the next step of our process, which is the creation of the ECS cluster.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset