Docker images are usually stored on Docker Hub, but AWS’s Elastic Container Registry can also be used. It’s a great solution and this post teaches you how to push Docker images to AWS’ Elastic Container Registry (ECR).
Create a Repository
Let’s start by using the aws-cli
to create a repository.
aws ecr create-repository --repository-name myname
This command successfully creates a repository and outputs the following JSON:
{
"repository": {
"repositoryArn": "arn:aws:ecr:eu-west-1:098765432123:repository/myname",
"registryId": "098765432123",
"repositoryName": "myname",
"repositoryUri": "098765432123.dkr.ecr.eu-west-1.amazonaws.com/myname",
"createdAt": 1543162198.0
}
}
It’s good to also point out that additionally, running a life-cycle policy to clean up older versions will save yourself a ton of time down the line. You can run it here as follows. It’s useful so that you don’t get blocked from pushing a new version in a bit.
aws ecr put-lifecycle-policy --registry-id 098765432123 --repository-name myname --lifecycle-policy-text '{"rules":[{"rulePriority":10,"description":"Expire older images","selection":{"tagStatus":"any","countType":"imageCountMoreThan","countNumber":100},"action":{"type":"expire"}}]}'
There are various other ways to clean up, such as by age. For now, though, we will clean up once there are 100 images in the repo.
Pushing and Pulling Images Locally
Start by authenticating your local Docker daemon against the ECR registry.
aws ecr get-login --registry-ids 098765432123 --no-include-email
This outputs a docker login and adds a new user-password pair for the Docker configuration. Copy-paste it, or run it like this instead:
$(aws ecr get-login --registry-ids 098765432123 --no-include-email)
Now pushing and pulling images is the same as what is usually done with Docker itself.
docker push 098765432123.dkr.ecr.eu-west-1.amazonaws.com/myname:0.0.1
docker pull 098765432123.dkr.ecr.eu-west-1.amazonaws.com/myname:0.0.1
Privileges required for Pushing Images
As ECR is within AWS, you use IAM users’ permissions to get the job done. It is always recommended to only give the permissions required to achieve a particular job and nothing more.
There are three policies that could be used for this:
AmazonEC2ContainerRegistryFullAccess
AmazonEC2ContainerRegistryPowerUser
AmazonEC2ContainerRegistryReadOnly
You can attach these policies to an IAM user like this:
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly --user-name andrewodendaal
You can also create your own policies, say for a CI/CD user to perform builds.
Start by creating an IAM group:
aws iam create-group --group-name myname-developers
{
"Group": {
"Path": "/",
"GroupName": "myname-developers",
"GroupId": "BBB4JRDMJSHFNJSNF3ARET8KJ",
"Arn": "arn:aws:iam::098765432123:group/myname-developers",
"CreateDate": "2018-10-25T11:45:42Z"
}
}
Now add a user:
aws iam add-user-to-group --group-name myname-developers --user-name andrewodendaal
This is what will be output:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:BatchGetImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:PutImage"
],
"Resource": "arn:aws:ecr:eu-west-1:098765432123:repository/myname"
}]
}
To create the policy, build out the following JSON and run a create-policy
with it:
aws iam create-policy --policy-name EcrPushPullMynameDevelopers --policy-document file://./policy.json
{
"Policy": {
"PolicyName": "EcrPushPullMynameDevelopers",
"PolicyId": "ANPAITNBFTFWZMI4WFOY6",
"Arn": "arn:aws:iam::098765432123:policy/EcrPushPullMynameDevelopers",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2018-10-25T12:00:15Z",
"UpdateDate": "2018-10-25T12:00:15Z"
}
}
Then finally attach it:
aws iam attach-group-policy --group-name myname-developers --policy-arn arn:aws:iam::098765432123:policy/EcrPushPullMynameDevelopers
Use ECR images in Kubernetes
When we attached the IAM policy AmazonEC2ContainerRegistryReadOnly
, it made every image available to every AWS account in the cluster.
To use it properly though, you should set the image
field of the pod template on your manifest to point to it:
image: 098765432123.dkr.ecr.eu-west-1.amazonaws.com/myname:0.0.1.
Tagging images
All Docker images push to a registry needs to be identified by a tag. This should be any alphanumeric value.
It’s always good practice to add semantic versioning
into tags.
MAJOR
.MINOR
.PATCH
, such as 1.0.2
.