Skip to main content

Overview

The Ecr construct provisions an AWS Elastic Container Registry repository for your container images. It extends the CDK Repository construct and applies Fjall defaults: vulnerability scanning on push, immutable tags, an untagged-image reclaim rule, and an environment-aware removal policy. Every Fjall application already has one. app.getDefaultContainerRegistry() creates a repository in the network stack on first call, named after the kebab-cased application name. Generated compute resources reference it directly, so most applications never instantiate Ecr by hand.

Resource Class

The default repository

fjall build and fjall deploy read that CloudFormation export to find the repository before pushing. Deriving the name yourself risks drifting from the construct.

Basic Usage

Ecr accepts four props only. It does not forward arbitrary CDK RepositoryProps.

Default Configuration

Tags are immutable by default. You cannot re-push :latest over an existing image. Push a unique tag per build, or pass tagMutability: TagMutability.MUTABLE for a repository that deliberately repushes the same tag (a dev slot, or a buildx cache repository).
Outside production, the repository and every image in it are deleted with the stack. A redeploy after that teardown pulls “not found” for any tag the old repository held. Pass removalPolicy: "RETAIN" on repositories whose images must outlive the stack.

Configuration Options

EcrLifecycle

Removal Policy

The default resolves from the deploy environment, which Fjall derives from the target account’s record and passes to CDK synth. It is not a flag you set on fjall deploy. CloudFormation refuses to delete a repository that still holds images, so DESTROY always ships with emptyOnDelete: true. The pair is deliberate, not a gentler DESTROY.
An unrecognised ENVIRONMENT value fails at synth rather than guessing. A typo such as ENVIRONMENT=prod would otherwise resolve DESTROY and delete images on teardown. Valid values are production, staging, development, platform, compliance and root.

Lifecycle Policy

The built-in rule

Every Ecr repository ships one lifecycle rule: expire untagged images after 7 days, at rulePriority: 1, tagStatus: UNTAGGED. Each CI push is an image. Without a reclaim rule a repository grows without bound. Fjall’s own web-app repository reached 1,473 images and roughly 55 GB before this default existed. Untagged expiry is safe for buildx provenance and SBOM pushes. ECR never expires an image still referenced by a live manifest list, so the untagged attestation and platform children of a tagged index become reclaimable only once the index goes.

Changing the retention window

Capping the image count

maxImageCount emits a second rule at priority 2 with tagStatus: ANY.
maxImageCount is opt-in for a reason. Count expiry is release-blind, so it cannot know which images your retained releases still reference. On monitored accounts Fjall’s release-aware retention janitor treats any tagStatus: any + imageCountMoreThan rule as the retired shape it supersedes and strips it from release-referenced repositories. Reach for it only on repositories outside release monitoring.

Owning the rules yourself

ECR permits exactly one untagged-selecting rule per policy and requires unique priorities. Adding your own rules on top of the built-in policy fails the stack at deploy. Pass lifecycle: false first, then add every rule yourself.

Image Scanning

Scanning runs on every push. Results appear in the ECR console and on the CloudWatch event bus.

Access Control

Ecr extends the CDK Repository, so every grant and policy method is available.

Cross-account pulls

Building and Pushing Images

Fjall builds and pushes for you. Do not wire a separate CodeBuild or GitHub Actions push path unless you have a reason to.
fjall deploy api builds and pushes as part of the deploy. Use --skip-build when the image is already in the repository.

Encryption

Ecr does not expose encryption or encryptionKey. Its four props are repositoryName, tagMutability, removalPolicy and lifecycle. For a customer-managed key, instantiate the CDK Repository construct directly and apply the defaults you want by hand.
AES-256 is the ECR default. Pass RepositoryEncryption.KMS without a key for the AWS-managed KMS key.

Outputs

Each Ecr construct emits one CloudFormation output and export: The export name matches the output key, so the CLI resolves the repository for fjall build and fjall deploy without guessing at the name.

Factory Pattern

EcrFactory

EcrFactory.build registers the repository with the application’s manifest collector, which is how the CLI discovers it at build and push time. A bare new Ecr(...) skips that registration silently.

StackBuilder

Complete Example

ContainerImage.fromEcrRepository grants pull to the task execution role for you.

Monitoring

Cost Optimisation

  • Storage bills per GB-month. The untagged reclaim rule is the cheapest lever, shorten untaggedRetentionDays on repositories with heavy CI churn.
  • Data transfer is free within the same region and billed per GB across regions. Use VPC endpoints for in-VPC pulls.
  • Shrink images with multi-stage builds before reaching for retention limits.
Check the AWS ECR pricing page for current rates.

Troubleshooting

Inspecting a repository

Run AWS commands against a connected account with Fjall-minted credentials:

Next Steps

Build Images

Build and push container images to the repository with fjall build.

ECS Cluster

Run containers from your ECR images on Fargate or EC2.

S3 Bucket

Store objects and static assets alongside your images.

CI/CD Deploys

Build, deploy and mint deploy tokens from a CI pipeline.