Header menu logo FsCDK

ECR Amazon ECR (Elastic Container Registry)

Amazon Elastic Container Registry (ECR) is a fully managed Docker container registry that makes it easy to store, manage, and deploy Docker container images. ECR eliminates the need to operate your own container repositories.

Quick Start

#r "../src/bin/Release/net8.0/publish/Amazon.JSII.Runtime.dll"
#r "../src/bin/Release/net8.0/publish/Constructs.dll"
#r "../src/bin/Release/net8.0/publish/Amazon.CDK.Lib.dll"
#r "../src/bin/Release/net8.0/publish/FsCDK.dll"

open FsCDK
open Amazon.CDK
open Amazon.CDK.AWS.ECR

Basic Repository

Create a repository with secure defaults.

stack "BasicECR" {
    let repo = ecrRepository "my-app" { () }
    // Uses secure defaults:
    // - Image scan on push: enabled
    // - Tag mutability: MUTABLE
    // - Encryption: AES256 (AWS managed)
    // - Removal policy: RETAIN
    ()
}

Repository with Lifecycle Rules

Automatically clean up old images to reduce storage costs.

stack "ECRWithLifecycle" {
    // Development repository
    let devRepo =
        ecrRepository "my-app-dev" {
            // Delete untagged images after 7 days
            lifecycleRule (ECRHelpers.deleteUntaggedAfterDays 7)

            // Keep only last 10 images
            lifecycleRule (ECRHelpers.keepLastNImages 10)
            ()
        }

    // Production repository
    let prodRepo =
        ecrRepository "my-app-prod" {
            // Delete untagged images after 14 days
            lifecycleRule (ECRHelpers.deleteUntaggedAfterDays 14)

            // Keep only last 30 images
            lifecycleRule (ECRHelpers.keepLastNImages 30)

            // Immutable tags for production
            imageTagMutability TagMutability.IMMUTABLE
        }

    ()
}

Repository with Standard Lifecycle Policies

Use predefined lifecycle policies for common scenarios.

stack "ECRStandardPolicies" {
    // Development repository with standard rules
    let devRepo = ecrRepository "app-dev" { () }
    // Add standard dev lifecycle rules using CDK directly:
    // - Delete untagged images after 7 days
    // - Keep last 10 images

    // Production repository with standard rules
    let prodRepo =
        ecrRepository "app-prod" { imageTagMutability TagMutability.IMMUTABLE }
    // Add standard prod lifecycle rules using CDK directly:
    // - Delete untagged images after 14 days
    // - Keep last 30 images`
    ()
}

Repository with Custom Lifecycle Rules

Define custom lifecycle rules for specific tag patterns.

stack "ECRCustomLifecycle" {
    let repo =
        ecrRepository "my-service" {
            // Delete staging images after 30 days
            lifecycleRule (ECRHelpers.deleteTaggedAfterDays "staging-" 30)

            // Delete feature branch images after 7 days
            lifecycleRule (ECRHelpers.deleteTaggedAfterDays "feature-" 7)

            // Delete PR images after 3 days
            lifecycleRule (ECRHelpers.deleteTaggedAfterDays "pr-" 3)

            // Keep untagged images for only 1 day
            lifecycleRule (ECRHelpers.deleteUntaggedAfterDays 1)
        }

    ()
}

Immutable Tags

Prevent tag overwrites in production repositories for better traceability.

stack "ImmutableTags" {
    let prodRepo =
        ecrRepository "prod-app" {
            imageTagMutability TagMutability.IMMUTABLE
            imageScanOnPush true
        }

    ()
}

Repository for Development

Optimized settings for development workflows.

stack "DevRepository" {
    let devRepo =
        ecrRepository "dev-app" {
            // Mutable tags for easy iteration
            imageTagMutability TagMutability.MUTABLE

            // Clean up frequently
            lifecycleRule (ECRHelpers.deleteUntaggedAfterDays 3)
            lifecycleRule (ECRHelpers.keepLastNImages 5)

            // Destroy on stack deletion (dev only!)
            removalPolicy RemovalPolicy.DESTROY
            emptyOnDelete true
        }

    ()
}

Image Scanning

Enable vulnerability scanning for container images.

stack "SecureRepository" {
    let repo =
        ecrRepository "secure-app" {
            // Scan all pushed images automatically
            imageScanOnPush true

            // Immutable tags for audit trail
            imageTagMutability TagMutability.IMMUTABLE
        }

    ()
}

Cross-Account Access

Share repositories across AWS accounts.

Note: Cross-account permissions must be configured using repository policies with the CDK API directly.

Repository Policy

Add resource-based policies for fine-grained access control.

Note: Repository policies must be configured using the CDK Repository directly.

Lifecycle Rule Helpers

FsCDK provides helper functions for common lifecycle patterns:

// Delete untagged images after N days
let cleanupUntagged = ECRHelpers.deleteUntaggedAfterDays 7

// Keep only the last N images
let keepRecent = ECRHelpers.keepLastNImages 10

// Delete images with tag prefix after N days
let cleanupFeatureBranches = ECRHelpers.deleteTaggedAfterDays "feature-" 7

// Standard development lifecycle
let devRules = ECRHelpers.standardDevLifecycleRules () // 7 days, 10 images

// Standard production lifecycle
let prodRules = ECRHelpers.standardProdLifecycleRules () // 14 days, 30 images

Best Practices

Security

Cost Optimization

Reliability

Performance

Operational Excellence

Default Settings

The ECR repository builder applies these secure defaults:

Tag Mutability

MUTABLE (Default)

IMMUTABLE

Image Scanning

ECR integrates with Amazon Inspector for vulnerability scanning:

Scan findings are available in: - ECR Console - Amazon Inspector - EventBridge events - Security Hub (if enabled)

Lifecycle Policies

Lifecycle policies automatically delete images based on:

Policies are evaluated in priority order. Use multiple rules to implement complex strategies.

Escape Hatch

For advanced scenarios, access the underlying CDK Repository:

`fsharp let repoResource = ecrRepository "my-app" { imageScanOnPush true }

// Access the CDK Repository for advanced configuration let cdkRepo = repoResource.Repository

// Add repository policy let policyDocument = ... // Create IAM policy document cdkRepo.AddToResourcePolicy(PolicyStatement(...))

// Grant pull access to a role cdkRepo.GrantPull(myRole)

// Grant push access to a role cdkRepo.GrantPush(myRole)

// Grant pull/push access cdkRepo.GrantPullPush(myRole) `

Integration with ECS/EKS

ECR works seamlessly with Amazon ECS and EKS:

`fsharp stack "ContainerStack" { // Create repository let repo = ecrRepository "my-service" { imageScanOnPush true imageTagMutability TagMutability.IMMUTABLE () }

// Use with ECS task definition
// let taskDef = FargateTaskDefinition(...)
// taskDef.AddContainer("app",
//     ContainerDefinitionOptions(
//         Image = ContainerImage.FromEcrRepository(repo.Repository, "v1.0.0")
//     ))`

} `

CI/CD Integration

Typical CI/CD workflow with ECR:

  1. Build Docker image
  2. Tag image (e.g., commit SHA, version)
  3. Authenticate to ECR (aws ecr get-login-password)
  4. Push image to repository
  5. ECR automatically scans image
  6. Deploy to ECS/EKS/Lambda if scan passes

Resources

namespace FsCDK
namespace Amazon
namespace Amazon.CDK
namespace Amazon.CDK.AWS
namespace Amazon.CDK.AWS.ECR
val stack: name: string -> StackBuilder
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
val repo: ECRRepositoryResource
val ecrRepository: name: string -> ECRRepositoryBuilder
<summary> Creates a new ECR repository builder with secure defaults. Example: ecrRepository "my-app" { imageScanOnPush true; lifecycleRule (deleteUntaggedAfterDays 7) } </summary>
val devRepo: ECRRepositoryResource
custom operation: lifecycleRule (LifecycleRule) Calls ECRRepositoryBuilder.LifecycleRule
module ECRHelpers from FsCDK
<summary> Helper functions for creating ECR lifecycle rules </summary>
val deleteUntaggedAfterDays: days: int -> LifecycleRule
<summary> Creates a lifecycle rule to delete untagged images after specified days </summary>
val keepLastNImages: count: int -> LifecycleRule
<summary> Creates a lifecycle rule to keep only the last N images </summary>
val prodRepo: ECRRepositoryResource
custom operation: imageTagMutability (TagMutability) Calls ECRRepositoryBuilder.ImageTagMutability
[<Struct>] type TagMutability = | MUTABLE = 0 | IMMUTABLE = 1
field TagMutability.IMMUTABLE: TagMutability = 1
val deleteTaggedAfterDays: tagPrefix: string -> days: int -> LifecycleRule
<summary> Creates a lifecycle rule to delete images with specific tag prefix after days </summary>
custom operation: imageScanOnPush (bool) Calls ECRRepositoryBuilder.ImageScanOnPush
field TagMutability.MUTABLE: TagMutability = 0
custom operation: removalPolicy (RemovalPolicy) Calls ECRRepositoryBuilder.RemovalPolicy
[<Struct>] type RemovalPolicy = | DESTROY = 0 | RETAIN = 1 | SNAPSHOT = 2 | RETAIN_ON_UPDATE_OR_DELETE = 3
field RemovalPolicy.DESTROY: RemovalPolicy = 0
custom operation: emptyOnDelete (bool) Calls ECRRepositoryBuilder.EmptyOnDelete
val cleanupUntagged: LifecycleRule
val keepRecent: LifecycleRule
val cleanupFeatureBranches: LifecycleRule
val devRules: LifecycleRule list
val standardDevLifecycleRules: unit -> LifecycleRule list
<summary> Creates a standard lifecycle policy for development repositories </summary>
val prodRules: LifecycleRule list
val standardProdLifecycleRules: unit -> LifecycleRule list
<summary> Creates a standard lifecycle policy for production repositories </summary>

Type something to start searching.