Skip to content

Terraform module to create AWS ECR (Elastic Container Registry)

License

Notifications You must be signed in to change notification settings

lgallard/terraform-aws-ecr

Repository files navigation

Terraform

terraform-aws-ecr

Terraform module to create AWS ECR (Elastic Container Registry) which is a fully-managed Docker container registry.

Usage

You can use this module to create an ECR registry using few parameters (simple example) or define in detail every aspect of the registry (complete example).

Check the examples for the simple and the complete snippets.

Simple example

This example creates an ECR registry using few parameters

module "ecr" {
  source = "lgallard/ecr/aws"

  name         = "ecr-repo-dev"

  # Tags
  tags = {
    Owner       = "DevOps team"
    Environment = "dev"
    Terraform   = true
  }
}

Complete example with logging

In this example, the registry is defined in detail including CloudWatch logging:

module "ecr" {
  source = "lgallard/ecr/aws"

  name                 = "ecr-repo-dev"
  scan_on_push        = true
  timeouts_delete     = "60m"
  image_tag_mutability = "IMMUTABLE"
  encryption_type     = "KMS"
  
  # Enable CloudWatch logging
  enable_logging     = true
  log_retention_days = 14

  // ...rest of configuration...
}

CloudWatch Logging

The module supports sending ECR API actions and image push/pull events to CloudWatch Logs. When enabled:

  • Creates a CloudWatch Log Group /aws/ecr/{repository-name}
  • Sets up necessary IAM roles and policies for ECR to write logs
  • Configurable log retention period (default: 30 days)

To enable logging:

module "ecr" {
  source = "lgallard/ecr/aws"
  
  name           = "ecr-repo-dev"
  enable_logging = true
  
  # Optional: customize retention period (in days)
  log_retention_days = 14  # Valid values: 0,1,3,5,7,14,30,60,90,120,150,180,365,400,545,731,1827,3653
}

The module outputs logging-related ARNs:

  • cloudwatch_log_group_arn - The ARN of the CloudWatch Log Group
  • logging_role_arn - The ARN of the IAM role used for logging

Complete example

In this example the register is defined in detailed.

module "ecr" {

  source = "lgallard/ecr/aws"

  name                 = "ecr-repo-dev"
  scan_on_push         = true
  timeouts_delete      = "60m"
  image_tag_mutability = "MUTABLE"
  prevent_destroy      = true  # Protect repository from accidental deletion


  # Note that currently only one policy may be applied to a repository.
  policy = <<EOF
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "repo policy",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:DescribeRepositories",
                "ecr:GetRepositoryPolicy",
                "ecr:ListImages",
                "ecr:DeleteRepository",
                "ecr:BatchDeleteImage",
                "ecr:SetRepositoryPolicy",
                "ecr:DeleteRepositoryPolicy"
            ]
        }
    ]
}
EOF

  # Only one lifecycle policy can be used per repository.
  # To apply multiple rules, combined them in one policy JSON.
  lifecycle_policy = <<EOF
{
    "rules": [
        {
            "rulePriority": 1,
            "description": "Expire untagged images older than 14 days",
            "selection": {
                "tagStatus": "untagged",
                "countType": "sinceImagePushed",
                "countUnit": "days",
                "countNumber": 14
            },
            "action": {
                "type": "expire"
            }
        },
        {
            "rulePriority": 2,
            "description": "Keep last 30 dev images",
            "selection": {
                "tagStatus": "tagged",
                "tagPrefixList": ["dev"],
                "countType": "imageCountMoreThan",
                "countNumber": 30
            },
            "action": {
                "type": "expire"
            }
        }
    ]
}
EOF

  # Tags
  tags = {
    Owner       = "DevOps team"
    Environment = "dev"
    Terraform   = true
  }

}

### Deleting ECR Repositories Protected with prevent_destroy

By default, ECR repositories created by this module have `prevent_destroy = true` set in their lifecycle configuration to prevent accidental deletion. When you need to remove a repository:

1. Set the `prevent_destroy` parameter to `false` for the module:

```hcl
module "ecr" {
  source = "lgallard/ecr/aws"

  name            = "ecr-repo-dev"
  prevent_destroy = false  # Allow repository to be destroyed
}
  1. Apply the configuration change:
terraform apply
  1. After successful apply, run destroy as normal:
terraform destroy

This approach allows protecting repositories by default while providing a controlled way to remove them when needed.

Requirements

Name Version
terraform >= 1.0.0
aws >= 4.0.0

Providers

Name Version
aws >= 4.0.0

Modules

No modules.

Resources

Name Type
aws_ecr_lifecycle_policy.lifecycle_policy resource
aws_ecr_repository.repo resource
aws_ecr_repository.repo_protected resource
aws_ecr_repository_policy.policy resource
aws_kms_alias.kms_key_alias resource
aws_kms_key.kms_key resource
aws_caller_identity.current data source

Inputs

Name Description Type Default Required
encryption_type The encryption type for the repository. Valid values are "KMS" or "AES256". string "AES256" no
force_delete Whether to delete the repository even if it contains images.
Setting this to true will delete all images in the repository when the repository is deleted.
Use with caution as this operation cannot be undone.
Defaults to false for safety.
bool false no
image_scanning_configuration Configuration block that defines image scanning configuration for the repository.
Set to null to use the scan_on_push variable setting.
Example: { scan_on_push = true }
object({
scan_on_push = bool
})
null no
image_tag_mutability The tag mutability setting for the repository.
- MUTABLE: Image tags can be overwritten
- IMMUTABLE: Image tags cannot be overwritten (recommended for production)
Defaults to MUTABLE to maintain backwards compatibility.
string "MUTABLE" no
kms_key The ARN of an existing KMS key to use for repository encryption.
Only applicable when encryption_type is set to 'KMS'.
If not specified when using KMS encryption, a new KMS key will be created.
string null no
lifecycle_policy JSON string representing the lifecycle policy.
If null (default), no lifecycle policy will be created.
See: https://docs.aws.amazon.com/AmazonECR/latest/userguide/lifecycle_policy_examples.html
string null no
name Name of the ECR repository. This name must be unique within the AWS account and region. string n/a yes
policy JSON string representing the repository policy.
If null (default), no repository policy will be created.
See: https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-policies.html
string null no
prevent_destroy Whether to protect the repository from being destroyed.
When set to true, the repository will have the lifecycle block with prevent_destroy = true.
When set to false, the repository can be destroyed.
This provides a way to dynamically control protection against accidental deletion.
Defaults to false to allow repository deletion.
bool false no
scan_on_push Indicates whether images should be scanned for vulnerabilities after being pushed to the repository.
- true: Images will be automatically scanned after each push
- false: Images must be scanned manually
Only used if image_scanning_configuration is null.
bool true no
tags A map of tags to assign to all resources created by this module.
Tags are key-value pairs that help you manage, identify, organize, search for and filter resources.
Example: { Environment = "Production", Owner = "Team" }
map(string) {} no
timeouts Timeout configuration for repository operations.
Specify as an object with a 'delete' key containing a duration string (e.g. "20m").
Example: { delete = "20m" }
object({
delete = optional(string)
})
{} no
timeouts_delete Deprecated: Use timeouts = { delete = "duration" } instead.
How long to wait for a repository to be deleted.
Specify as a duration string, e.g. "20m" for 20 minutes.
string null no
enable_logging Whether to enable CloudWatch logging for the repository.
When set to true, logs for ECR API actions and image push/pull events will be sent to CloudWatch Logs.
Defaults to false to disable logging.
bool false no
log_retention_days The number of days to retain logs in the CloudWatch Log Group.
Valid values: 0,1,3,5,7,14,30,60,90,120,150,180,365,400,545,731,1827,3653.
Defaults to 30 days.
number 30 no

Outputs

Name Description
kms_key_arn The ARN of the KMS key used for repository encryption.
registry_id ID of the ECR registry
repository_arn ARN of the ECR repository
repository_name Name of the ECR repository
repository_url URL of the ECR repository
cloudwatch_log_group_arn The ARN of the CloudWatch Log Group created for logging.
logging_role_arn The ARN of the IAM role used for logging.