> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artosai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ECR Module

> Amazon Elastic Container Registry repositories for Artos application images

## Overview

The ECR (Elastic Container Registry) Module manages container image repositories for the Artos platform. It creates separate repositories for environment-specific application components and shared third-party services, with configurable lifecycle policies, security scanning, encryption, and cross-account access controls.

### Key Features

* **Environment Isolation**: Separate repositories per environment (development, staging, production)
* **Automatic Image Cleanup**: Lifecycle policies to manage storage costs
* **Security Scanning**: Automatic vulnerability scanning on image push
* **Encryption**: Support for AES256 and KMS encryption
* **Cross-Account Access**: Enable image sharing across AWS accounts
* **Third-Party Image Management**: Centralized repositories for shared dependencies

## Container Images

The module creates repositories for two types of container images: **Environment-Specific** images that are isolated per environment, and **Third-Party/Shared** images that are centralized across environments.

### Environment-Specific Images

These repositories are created for each environment (development, staging, production) and contain custom Artos application code.

#### 1. Backend API (`artos-postgres-eks-backend`)

**Repository Name**: `{environment}/artos-postgres-eks-backend`

The main application backend API server that handles HTTP requests, business logic, and database interactions.

**Contains**:

* FastAPI REST API server for core Artos platform logic and routes
* Database models and migrations
* Authentication and authorization logic

**Typical Images**:

```bash theme={null}
development/artos-postgres-eks-backend:latest
development/artos-postgres-eks-backend:v1.2.3
staging/artos-postgres-eks-backend:v1.2.3
production/artos-postgres-eks-backend:v1.2.3
```

#### 2. Celery Workers (`artos-postgres-eks-celery`)

**Repository Name**: `{environment}/artos-postgres-eks-celery`

Asynchronous task workers for background job processing, scheduled tasks, and long-running operations.

**Contains**:

* Celery worker processes
* Task definitions and handlers
* Background job processors
* Scheduled task runners
* Queue consumers

**Typical Images**:

```bash theme={null}
development/artos-postgres-eks-celery:latest
staging/artos-postgres-eks-celery:v1.2.3
production/artos-postgres-eks-celery:v1.2.3
```

**Use Cases**:

* Document generation workflows
* Document editing workflows

#### 3. Frontend Application (`frontend`)

**Repository Name**: `{environment}/frontend`

The user-facing web application frontend built with modern JavaScript frameworks.

**Contains**:

* frontend UI and functionality for the Artos platform

**Typical Images**:

```bash theme={null}
development/frontend:latest
development/frontend:feature-new-ui
staging/frontend:v2.1.0
production/frontend:v2.1.0
```

### Third-Party/Shared Images

These repositories are created once (typically in a shared or production account) and used across all environments to avoid duplication and ensure consistency.

<Note>
  **Important**: Set `create_thirdparty_repos = true` in **only one environment** (typically production or a shared services account) to avoid repository name conflicts. Other environments should reference these shared repositories.
</Note>

#### 4. Redis Cache (`thirdparty/redis`)

**Repository Name**: `thirdparty/redis`

Redis container images used for caching, session storage, and message brokering.

**Purpose**:

* Application caching layer
* Celery message broker
* Rate limiting data store

**Typical Images**:

```bash theme={null}
thirdparty/redis:7.2-alpine
thirdparty/redis:7.0-alpine
```

#### 5. OnlyOffice Document Server (`thirdparty/onlyoffice`)

**Repository Name**: `thirdparty/onlyoffice`

OnlyOffice Document Server for collaborative document editing and viewing.

**Purpose**:

* Word document editing (DOCX)
* Real-time collaboration

**Typical Images**:

```bash theme={null}
thirdparty/onlyoffice:7.5
thirdparty/onlyoffice:7.4
```

#### 6. LiteLLM Proxy (`thirdparty/litellm`)

**Repository Name**: `thirdparty/litellm`

LiteLLM proxy server for unified LLM (Large Language Model) API access.

**Purpose**:

* Unified interface for multiple LLM providers (OpenAI, Anthropic, etc.)
* API key management and rotation
* Request rate limiting and cost tracking
* Load balancing across LLM endpoints
* Caching for improved performance

**Typical Images**:

```bash theme={null}
thirdparty/litellm:latest
thirdparty/litellm:v1.0.0
```

#### 7. PropelAuth (`thirdparty/propelauth`)

**Repository Name**: `thirdparty/propelauth`

PropelAuth authentication and user management service.

**Purpose**:

* User authentication and authorization
* SSO (Single Sign-On) integration
* Multi-factor authentication (MFA)
* User management and organization features
* OAuth and SAML support

**Typical Images**:

```bash theme={null}
thirdparty/propelauth:latest
thirdparty/propelauth:v2.0.0
```

## Image Management Policies

### 1. Lifecycle Policies

Lifecycle policies automatically delete older images to manage storage costs while retaining recent versions.
Note: all `max_image_count` values are set to 0 to ensure all versions are stored in ECR.

**How It Works**:

* Triggered when image count exceeds `max_image_count`
* Deletes oldest images first (by push timestamp)
* Applies to both tagged and untagged images
* Runs automatically (no manual intervention needed)

**Policy Behavior**:

| `max_image_count` | Behavior                                             |
| ----------------- | ---------------------------------------------------- |
| `null` or `0`     | No lifecycle policy (keep all images indefinitely)   |
| `1-1000`          | Keep only the specified number of most recent images |

**Example Lifecycle Policy**:

```json theme={null}
{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Keep last 10 images",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}
```

### 2. Cross-Account Access Policies

Cross-account policies enable other AWS accounts to pull images from your ECR repositories, useful for multi-account architectures or shared services.
Note: default terraform has cross\_account\_ids set to an empty list. Cross account ids are usually added manually after the terraform is spun up.

**Policy Configuration**:

```hcl theme={null}
enable_cross_account_access = true
cross_account_ids = [
  "123456789012",  # Production account
  "234567890123"   # Staging account
]
```

**Granted Permissions**:

* `ecr:GetDownloadUrlForLayer` - Download image layers
* `ecr:BatchGetImage` - Retrieve image metadata
* `ecr:BatchCheckLayerAvailability` - Check if layers exist

**Example Repository Policy**:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCrossAccountPull",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:root",
          "arn:aws:iam::234567890123:root"
        ]
      },
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability"
      ]
    }
  ]
}
```

**Use Cases**:

* **Centralized Image Registry**: Production account hosts all images, other accounts pull as needed
* **Multi-Region Deployments**: Share images across regions via cross-account replication
* **Shared Services**: Development account provides common third-party images to all environments

### 3. Image Scanning

Automatically scans container images for security vulnerabilities (CVEs) upon push.

**Configuration**:

```hcl theme={null}
scan_on_push = true  # Enable automatic scanning (default)
```

**Scanning Process**:

1. Image is pushed to ECR repository
2. ECR triggers automatic vulnerability scan
3. Results available in AWS Console or via API within minutes
4. Findings categorized by severity: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL

**Viewing Scan Results**:

```bash theme={null}
# Get scan findings for an image
aws ecr describe-image-scan-findings \
    --repository-name production/artos-postgres-eks-backend \
    --image-id imageTag=v1.2.3 \
    --region us-east-1
```

**CI/CD Integration**:

```yaml theme={null}
# Example GitHub Actions workflow
- name: Scan for vulnerabilities
  run: |
    aws ecr wait image-scan-complete \
      --repository-name ${{ env.REPOSITORY }} \
      --image-id imageTag=${{ env.IMAGE_TAG }}
    
    SCAN_FINDINGS=$(aws ecr describe-image-scan-findings \
      --repository-name ${{ env.REPOSITORY }} \
      --image-id imageTag=${{ env.IMAGE_TAG }} \
      --query 'imageScanFindings.findingSeverityCounts')
    
    # Fail build if critical vulnerabilities found
    if echo $SCAN_FINDINGS | grep -q "CRITICAL"; then
      echo "Critical vulnerabilities found!"
      exit 1
    fi
```

### 5. Encryption

All images are encrypted at rest using either AWS-managed or customer-managed encryption keys.

**Configuration Options**:

**AES256 (Default - AWS-Managed)**:

```hcl theme={null}
encryption_type = "AES256"  # No additional configuration needed
```

**KMS (Customer-Managed Keys)**:

```hcl theme={null}
encryption_type = "KMS"
kms_key_arn     = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
```

## Module Configuration

### Basic Configuration

```hcl theme={null}
module "ecr" {
  source = "./modules/ecr"

  environment = "production"

  # Standard security settings
  scan_on_push         = true
  image_tag_mutability = "IMMUTABLE"
  encryption_type      = "AES256"

  # Keep last 10 images
  max_image_count = 10

  # Do not create third-party repos (use shared ones)
  create_thirdparty_repos = false

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}
```

### Production Configuration with KMS

```hcl theme={null}
module "ecr_production" {
  source = "./modules/ecr"

  environment = "production"

  # Production security settings
  scan_on_push         = true
  image_tag_mutability = "IMMUTABLE"  # Prevent tag overwrites
  encryption_type      = "KMS"
  kms_key_arn          = module.kms.ecr_key_arn

  # Retain more images for rollback capability
  max_image_count = 20

  # Enable cross-account access for disaster recovery
  enable_cross_account_access = true
  cross_account_ids = [
    "123456789012"  # DR account
  ]

  create_thirdparty_repos = false

  tags = {
    Environment = "production"
    Compliance  = "hipaa"
    BackupPlan  = "daily"
  }
}
```

### Shared Services Configuration

```hcl theme={null}
# Create third-party repositories in a shared services account
module "ecr_shared" {
  source = "./modules/ecr"

  environment = "shared"

  # Shared repository settings
  scan_on_push         = true
  image_tag_mutability = "MUTABLE"  # Allow updates to shared images
  encryption_type      = "AES256"

  # Keep fewer images for third-party dependencies
  max_image_count = 5

  # CREATE third-party repos in shared account only
  create_thirdparty_repos = true

  # Allow all environment accounts to pull
  enable_cross_account_access = true
  cross_account_ids = [
    "111111111111",  # Development account
    "222222222222",  # Staging account
    "333333333333"   # Production account
  ]

  tags = {
    Environment = "shared"
    Purpose     = "third-party-images"
  }
}
```

### Development Configuration

```hcl theme={null}
module "ecr_dev" {
  source = "./modules/ecr"

  environment = "development"

  # Relaxed settings for development
  scan_on_push         = true
  image_tag_mutability = "MUTABLE"   # Allow tag overwrites
  encryption_type      = "AES256"

  # Keep only recent images to minimize costs
  max_image_count = 3

  # Reference shared third-party repos
  create_thirdparty_repos = false

  tags = {
    Environment = "development"
    CostCenter  = "engineering"
  }
}
```

## Repository Naming Convention

The module follows a consistent naming pattern for easy identification and organization:

**Environment-Specific Repositories**:

```
{environment}/artos-postgres-eks-backend
{environment}/artos-postgres-eks-celery
{environment}/frontend
```

**Third-Party/Shared Repositories**:

```
thirdparty/redis
thirdparty/onlyoffice
thirdparty/litellm
thirdparty/propelauth
```

**Examples**:

```
development/artos-postgres-eks-backend
staging/artos-postgres-eks-celery
production/frontend
thirdparty/redis
```

## Pushing Images to ECR

### Authenticate Docker to ECR

```bash theme={null}
# Get authentication token and login
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 Push Application Images

```bash theme={null}
# Build backend image
docker build -t artos-backend:v1.2.3 -f backend/Dockerfile .

# Tag for ECR
docker tag artos-backend:v1.2.3 \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/production/artos-postgres-eks-backend:v1.2.3

# Push to ECR
docker push \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/production/artos-postgres-eks-backend:v1.2.3

# Also push as 'latest'
docker tag artos-backend:v1.2.3 \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/production/artos-postgres-eks-backend:latest

docker push \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/production/artos-postgres-eks-backend:latest
```

### Pull Third-Party Images

```bash theme={null}
# Pull Redis from Docker Hub
docker pull redis:7.2-alpine

# Tag for your ECR
docker tag redis:7.2-alpine \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/thirdparty/redis:7.2-alpine

# Push to your ECR
docker push \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/thirdparty/redis:7.2-alpine
```

## Related Modules

* [EKS Module](./eks.mdx) - References ECR images for Kubernetes deployments
* [Bastion Module](./bastion.mdx) - Uses kubectl binary stored in S3 or ECR
* [Monitoring Module](./monitoring.mdx) - Tracks ECR metrics and image scan results

***

<Note>
  **Module Maintenance**: This module is compatible with Terraform 1.0+ and AWS Provider 5.x. All repositories are automatically tagged with environment and component metadata for resource tracking and cost allocation.
</Note>
