push docker image to ECR using terraform

Viewed 9396

Using terraform to pull and reload an public image from Dockerhub (or just custom image) to ECR. I was thinking about something like

# Create ECR repository
resource "aws_ecr_repository" "ecr_repo" {
  name                 = var.ecr_name
}
# Docker image
resource "null_resource" "docker_hub" {
        ......
        ......
  depends_on = [aws_ecr_repository.ecr_repo]
}

Basically create an ECR repo and then uplodading an image... I'm new to terrform and been spending quite a lot of time on this. so anything would help. Thanks

2 Answers

Terraform was really only designed for creating infrastructure like the AWS ECR repository and policy document resources. It is possible to coerce Terraform to do what you want using the local-exec provisioner which would let you add arbitrary commands, but it's not really best practice. As they mention in the documentation Terraform provisioners should be treated as a last resort.

The simplest way forward would be to just combine Terraform with Docker and AWS CLI commands to build and push the image:

# ...terraform commands    
docker build -t ${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com/${REPO} .

aws ecr get-login-password \
    --region ${REGION} \
| docker login \
    --username AWS \
    --password-stdin ${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com

docker push ${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com/${REPO}

Alternatively, you could use HashiCorp Packer which was designed for this purpose (building VM/container images) and has great integration with Terraform. This would mean more of a learning curve though, as Packer doesn't use Dockerfiles. Anyway, if you go down this path you'd need to use the Docker builder combined with the Docker push post-processor.

you would use the aws_ecr_repository resource as you have done, and any other resources you would like to use in the ECR AWS Provider. The one below is the aws_ecr_repository_policy to be able to set the permissions on the repository.

resource "aws_ecr_repository_policy" "demo-repo-policy" {
  repository = aws_ecr_repository.demo-repository.name
  policy     = <<EOF
  {
    "Version": "2008-10-17",
    "Statement": [
      {
        "Sid": "adds full ecr access to the demo repository",
        "Effect": "Allow",
        "Principal": "*",
        "Action": [
          "ecr:BatchCheckLayerAvailability",
          "ecr:BatchGetImage",
          "ecr:CompleteLayerUpload",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetLifecyclePolicy",
          "ecr:InitiateLayerUpload",
          "ecr:PutImage",
          "ecr:UploadLayerPart"
        ]
      }
    ]
  }
  EOF
}

Afterwards you can use the attributes from the resources you have used, for the docker push command

docker push ${aws_account_id}.dkr.ecr.${region}.amazonaws.com/${repository-name}

more information in the following tutorial https://www.oneworldcoders.com/blog/using-terraform-to-provision-amazons-ecr-and-ecs-to-manage-containers-docker

Related