Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fjall.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

ECR (Elastic Container Registry) stores your Docker container images for ECS deployments. Fjall automatically creates and manages ECR repositories when you use ComputeFactory with type: "ecs" - you typically don’t need to create them manually.

Automatic Management

When you deploy ECS containers with Fjall, ECR repositories are automatically:
  • Created with your application name
  • Configured with image scanning
  • Set up with lifecycle policies
  • Granted access to your ECS tasks
// Fjall handles ECR automatically
const api = app.addCompute(
  ComputeFactory.build("API", {
    type: "ecs",
    ecsType: "fargate",
    // ECR repository created automatically
  })
);

Pushing Images

Using Docker CLI

# Login to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  123456789012.dkr.ecr.us-east-1.amazonaws.com

# Build and tag image
docker build -t myapp .
docker tag myapp:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest

# Push to ECR
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest

In CI/CD Pipeline

# GitHub Actions example
- name: Login to Amazon ECR
  uses: aws-actions/amazon-ecr-login@v1

- name: Build and push
  env:
    ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    ECR_REPOSITORY: myapp
    IMAGE_TAG: ${{ github.sha }}
  run: |
    docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
    docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

Manual Repository Creation

Only create explicit ECR repositories if you need:
  • Shared repositories across multiple applications
  • Custom lifecycle or scanning policies
  • Cross-account repository access
import { Repository } from "aws-cdk-lib/aws-ecr";

const sharedRepo = new Repository(this, "SharedImages", {
  repositoryName: "shared-base-images",
  imageScanOnPush: true,
  lifecycleRules: [
    {
      maxImageCount: 10,
      description: "Keep only 10 images",
    },
  ],
});

Using Custom Repositories

Specify Repository in ComputeFactory

import { Repository } from "aws-cdk-lib/aws-ecr";

const customRepo = Repository.fromRepositoryName(
  this,
  "CustomRepo",
  "my-custom-repo"
);

const api = app.addCompute(
  ComputeFactory.build("API", {
    type: "ecs",
    ecsType: "fargate",
    ecrRepository: customRepo,
  })
);

Use Specific Image Tag

import { RepositoryImage } from "aws-cdk-lib/aws-ecs";

const api = app.addCompute(
  ComputeFactory.build("API", {
    type: "ecs",
    ecrRepository: RepositoryImage.fromEcrRepository(
      Repository.fromRepositoryName(this, "Repo", "myapp"),
      "v1.2.3"
    ),
  })
);

Lifecycle Policies

Keep recent images, remove old ones:
const repo = new Repository(this, "Repo", {
  lifecycleRules: [
    {
      description: "Keep last 5 production images",
      tagPrefixList: ["prod"],
      maxImageCount: 5,
    },
    {
      description: "Expire untagged images after 7 days",
      maxImageAge: Duration.days(7),
      tagStatus: TagStatus.UNTAGGED,
    },
  ],
});

Image Scanning

Automatically scan for vulnerabilities:
const repo = new Repository(this, "Repo", {
  imageScanOnPush: true, // Scan every pushed image
});

Lambda Container Images

Use ECR for Lambda container images:
import { Repository } from "aws-cdk-lib/aws-ecr";
import { Runtime, Code } from "aws-cdk-lib/aws-lambda";

const lambdaRepo = Repository.fromRepositoryName(
  this,
  "LambdaImages",
  "lambda-containers"
);

const containerLambda = app.addCompute(
  ComputeFactory.build("Worker", {
    type: "lambda",
    code: Code.fromEcrImage(lambdaRepo, {
      tagOrDigest: "latest",
    }),
    handler: Handler.FROM_IMAGE,
    runtime: Runtime.FROM_IMAGE,
  })
);

Cross-Account Access

Share images with other AWS accounts:
import { AccountPrincipal } from "aws-cdk-lib/aws-iam";

repo.grantPull(new AccountPrincipal("123456789012"));

Repository URLs

Get repository information:
// Repository ARN
console.log(repo.repositoryArn);
// arn:aws:ecr:us-east-1:123456789012:repository/myapp

// Repository URI
console.log(repo.repositoryUri);
// 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp

// Use in environment variables
const api = app.addCompute(
  ComputeFactory.build("API", {
    type: "ecs",
    containerEnvironment: {
      IMAGE_REPO: repo.repositoryUri,
    },
  })
);

Best Practices

  • Let Fjall manage ECR for standard ECS deployments
  • Enable image scanning to detect vulnerabilities
  • Use lifecycle policies to limit storage costs
  • Tag images with version numbers (e.g., v1.2.3, git SHA)
  • Use separate repos for different applications
  • Implement CI/CD for automated image builds
  • Monitor scan results and update base images regularly

Common Issues

Image Pull Errors

If ECS can’t pull images:
  • Verify ECR repository exists in the same region
  • Check ECS task role has ECR pull permissions (Fjall handles this automatically)
  • Ensure image tag exists in repository
  • Confirm repository name matches configuration

Large Image Sizes

Optimize image size:
  • Use multi-stage Docker builds
  • Choose minimal base images (alpine, distroless)
  • Remove unnecessary files and dependencies
  • Combine RUN commands to reduce layers

See Also