Skip to content

github-workflows-dojo360-container-cd

Deploy containerized applications to AWS ECS/Azure ACS using Dojo360 Container CD workflow with blue-green and rolling update strategies

active
IDE:
claude
codex
vscode
Version:
1.0.0
Owner:pcorazao
github-actions
workflow
dojo360

Container CD (Continuous Deployment) Skill

Overview

The Dojo360 Container-CD workflow deploys containerized applications to cloud environments (AWS ECS/Azure ACS) using Terraform-managed infrastructure. It supports both rolling update and blue-green deployment strategies, multi-service deployments, and integrates with container registries (ECR, Artifactory, ACR).

Workflow Reference

Repository: dojo360/pipelines-workflows
Workflow: .github/workflows/container-cd.yml
Version: v2.0.0 (stable) or @beta (latest)
Documentation: web/container-cd/index.md

Key Features

  • Multi-Cloud Support: Deploy to AWS ECS or Azure Container Services
  • Deployment Strategies:
    • Rolling updates (ECS native)
    • Blue-green deployments (AWS CodeDeploy)
    • Multi-service parallel deployments
    • AWS Batch job execution
  • Authentication: OIDC or InstanceProfile authentication based on cloud-type
  • Container Sources: Support for ECR, Artifactory, ACR, and custom registries
  • Terraform Integration: Full Terraform lifecycle management (plan, apply)
  • State Management: Remote state support (Azure, AWS S3, GCS)
  • Artifact Promotion: Automatic artifact promotion from SaaS Artifactory
  • Secrets Management: PRM, Volcan, Terraform Enterprise integration
  • End-to-End Testing: Optional E2E test execution post-deployment

Prerequisites

  1. Metadata Onboarding:

  2. OIDC Configuration:

  3. Infrastructure Setup:

    • ECS cluster must exist (created via infrastructure workflow)
    • Task definitions and services configured
    • CodeDeploy application and deployment group (for blue-green)
  4. Container Image:

    • Image must be available in specified registry
    • Proper tagging strategy implemented

Requirements

  • Terraform: ~> 1.9.x
  • AWS Provider: ~> 5.xx (for AWS operations)
  • AzureRM Provider: ~> 3.xx (for Azure operations)
  • GCP Provider: ~> 6.xx (for GCP operations)

Required Inputs

InputDescriptionExample
aide-idAideId from https://aide.optum.com for metadata<your-aide-id>
cloud-typeCloud platform for metadata fetchingawsOptum, awsChc20, azureOptum
domainDomain for metadata<your-domain>
environmentTarget deployment environmentdev, qa, cert, prod
team-nameTeam name for metadata<your-team-name>

Common Optional Inputs

InputDescriptionDefaultExample
artifact-environmentSource artifact environment for promotion''RELEASE, CERTIFIED
comment-on-prComment Terraform plan output on PRfalsetrue
container-registryCloud-specific container registry (ECR/ACR)''<account>.dkr.ecr.us-east-1.amazonaws.com
deployment-controller-typeDeployment strategy typeECSCODE_DEPLOY, MULTI_SERVICES_CODE_DEPLOY, batch-job
docker-imageFully qualified image path''/repo-name/image-name
docker-repositoryDocker registry URLdocker.repo1.uhc.comcentraluhg.jfrog.io, artifactory.healthcareit.net
docker-tagImage tag to deploy''latest, v1.0.0, pr-123
e2e-tests-enabledEnable E2E tests after deploymentfalsetrue
e2e-workflow-fileE2E workflow file to execute''.github/workflows/e2e-tests.yml
e2e-workflow-inputsJSON input overrides for E2E workflow''{"environment": "qa"}
jfrog-project-keyJFrog SaaS Artifactory project key''your-project-docker-vir
jfrog-release-bundle-nameRelease bundle name for promotion''your-app-v1.0.0
remote-state-file-nameTerraform remote state file name''terraform.tfstate
remote-state-folder-nameTerraform remote state folder''container-infra
run-plan-onlyOnly run terraform plan (no apply)falsetrue
runner-labelsCustom runner labels''uhg-runner,docker
terraform-directoryPath to Terraform code.terraform/ecs
terraform-loggingTerraform log levelofftrace, debug, info
terraform-prm-secretsComma-separated PRM secrets to map''DB_PASSWORD,API_KEY
terraform-vars-filesComma-separated tfvars files''dev.tfvars,common.tfvars
terraform-vars-valuesInline Terraform variables''instance_count=3,enable_logging=true
terraform-versionTerraform version to use~> 1.91.9.5
volcan-decrypt-secretsDecrypt secrets from Volcanfalsetrue

Deployment Controller Types

1. ECS (Rolling Update) - Default

  • Native ECS rolling update
  • Gradual replacement of tasks
  • No downtime if configured properly

Required Terraform Outputs:

  • ecs_cluster
  • ecs_service
  • task_definition_family
  • task_definition_tags_all

2. CODE_DEPLOY (Blue-Green)

  • AWS CodeDeploy blue-green deployment
  • Traffic shifting strategies
  • Automatic rollback on failure

Required Terraform Outputs:

  • ecs_cluster
  • ecs_service
  • task_definition_family
  • codedeploy_application
  • codedeploy_deployment_group
  • appspec_file_arn
  • task_definition_tags_all

3. MULTI_SERVICES_CODE_DEPLOY

  • Deploy multiple ECS services in parallel
  • Shared CodeDeploy application
  • All services must be in same cluster

Required Terraform Outputs (Map Format):

  • ecs_cluster (string)
  • codedeploy_application (string)
  • ecs_service (map)
  • task_definition_family (map)
  • codedeploy_deployment_group (map)
  • appspec_file_arn (map)
  • task_definition_tags_all (map)

4. batch-job

  • AWS Batch job execution
  • Container-based batch processing

Required Terraform Outputs:

  • job_definition
  • job_queue
  • container_overrides

Secrets Management

The workflow supports multiple secret management strategies:

Required Secrets

  • GH_TOKEN - GitHub token with repository permissions

PRM (Privileged Resource Manager)

Use terraform-prm-secrets to map PRM secrets to Terraform variables:

terraform-prm-secrets: "DB_PASSWORD,API_KEY,JWT_SECRET"

Volcan Vault

Set volcan-decrypt-secrets: true to decrypt secrets from Volcan vault.

Terraform Enterprise

Secrets can be stored in Terraform Cloud/Enterprise workspaces.

Terraform State Management

Azure Backend (Default)

backend-type: "azurerm"
azurerm-backend-resource-group-name: "<resource-group>"
azurerm-backend-storage-account-name: "<storage-account>"
azurerm-backend-container-name: "<container>"
azurerm-backend-key: "terraform.tfstate"

AWS S3 Backend

backend-type: "s3"
aws-s3-bucket-name: "<bucket-name>"
aws-s3-key: "terraform.tfstate"
aws-s3-region: "us-east-1"

GCS Backend

backend-type: "gcs"
gcs-backend-bucket-name: "<bucket-name>"
gcs-backend-state-prefix: "terraform/state"

Required Workflow Permissions

permissions:
  actions: read
  contents: write
  id-token: write  # Required for OIDC authentication
  pull-requests: read
  security-events: write

Usage Examples

Example 1: Basic Rolling Update Deployment (AWS ECS)

name: Deploy to AWS ECS

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        required: true
        type: choice
        options:
          - dev
          - qa
          - cert
          - prod

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: read
  security-events: write

jobs:
  deploy:
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: ${{ inputs.environment }}
      team-name: "<your-team-name>"
      
      # Container image details
      docker-image: "/my-app/api"
      docker-repository: "centraluhg.jfrog.io"
      docker-tag: "latest"
      jfrog-project-key: "your-project-docker-vir"
      
      # Terraform configuration
      terraform-directory: "terraform/ecs"
      deployment-controller-type: "ECS"
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Example 2: Blue-Green Deployment with CodeDeploy

name: Blue-Green Deployment

on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'terraform/**'
      - 'Dockerfile'

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: read
  security-events: write

jobs:
  deploy:
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: "prod"
      team-name: "<your-team-name>"
      
      # Blue-green deployment
      deployment-controller-type: "CODE_DEPLOY"
      
      # Container image
      docker-image: "/my-app/api"
      docker-repository: "centraluhg.jfrog.io"
      docker-tag: ${{ github.sha }}
      jfrog-project-key: "your-project-docker-vir"
      
      # Terraform configuration
      terraform-directory: "terraform/ecs-bluegreen"
      terraform-vars-files: "prod.tfvars"
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Example 3: Multi-Service Deployment

name: Multi-Service Deployment

on:
  workflow_dispatch:
    inputs:
      services:
        description: 'Services to deploy'
        required: true
        default: 'all'

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: read
  security-events: write

jobs:
  deploy:
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: "qa"
      team-name: "<your-team-name>"
      
      # Multi-service deployment
      deployment-controller-type: "MULTI_SERVICES_CODE_DEPLOY"
      
      # Container configuration
      docker-repository: "centraluhg.jfrog.io"
      jfrog-project-key: "your-project-docker-vir"
      
      # Terraform configuration
      terraform-directory: "terraform/multi-service"
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Example 4: Plan-Only Mode for PR Validation

name: Terraform Plan on PR

on:
  pull_request:
    branches: [main]
    paths:
      - 'terraform/**'

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: write
  security-events: write

jobs:
  plan:
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: "dev"
      team-name: "<your-team-name>"
      
      # Plan-only mode
      run-plan-only: true
      comment-on-pr: true
      
      # Container details
      docker-image: "/my-app/api"
      docker-repository: "centraluhg.jfrog.io"
      docker-tag: "pr-${{ github.event.pull_request.number }}"
      
      # Terraform configuration
      terraform-directory: "terraform/ecs"
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Example 5: Deployment with E2E Tests

name: Deploy with E2E Tests

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment'
        required: true
        type: choice
        options:
          - qa
          - cert

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: read
  security-events: write

jobs:
  deploy:
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: ${{ inputs.environment }}
      team-name: "<your-team-name>"
      
      # Container configuration
      docker-image: "/my-app/api"
      docker-repository: "centraluhg.jfrog.io"
      docker-tag: ${{ github.sha }}
      jfrog-project-key: "your-project-docker-vir"
      
      # Terraform configuration
      terraform-directory: "terraform/ecs"
      
      # E2E testing
      e2e-tests-enabled: true
      e2e-workflow-file: ".github/workflows/e2e-tests.yml"
      e2e-workflow-inputs: |
        {
          "environment": "${{ inputs.environment }}",
          "api_url": "https://api-${{ inputs.environment }}.example.com"
        }
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Example 6: Chaining CI and CD Workflows

name: CI/CD Pipeline

on:
  push:
    branches: [main]

permissions:
  actions: read
  contents: write
  id-token: write
  pull-requests: read
  security-events: write
  checks: write

jobs:
  # CI Job - Build and publish container image
  ci:
    uses: uhg-pipelines/ci-workflows/.github/workflows/docker-ci.yml@v2
    with:
      jfrog-project-key: "your-project"
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/my-app:${{ github.sha }}
      docker-context: "."
      docker-dockerfile: "Dockerfile"
  
  # CD Job - Deploy to environment
  deploy:
    needs: ci
    uses: dojo360/pipelines-workflows/.github/workflows/[email protected]
    with:
      # Required inputs
      aide-id: "<your-aide-id>"
      cloud-type: "awsOptum"
      domain: "<your-domain>"
      environment: "dev"
      team-name: "<your-team-name>"
      
      # Use docker-tag from CI workflow
      docker-repository: "centraluhg.jfrog.io"
      docker-tag: ${{ needs.ci.outputs.uploaded-docker-tag }}
      jfrog-project-key: "your-project-docker-vir"
      
      # Terraform configuration
      terraform-directory: "terraform/ecs"
      
    secrets:
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

Cloud-Type Specific Configurations

awsOptum (AWS with OIDC)

  • Uses OIDC authentication
  • Requires AWS OIDC configuration
  • Leverages uhg-runner for execution
  • Uses Terraform AWS provider mirror

awsChc20 (AWS Legacy)

  • Uses InstanceProfile authentication
  • Leverages legacy CHC runners
  • Uses Terraform AWS provider mirror

azureOptum (Azure with OIDC)

  • Uses OIDC authentication
  • Requires Azure OIDC configuration
  • Uses AzureRM provider
  • Supports Azure Container Services

Project Structure Requirements

your-repository/
├── .github/
│   └── workflows/
│       └── container-cd.yml          # Your workflow file
├── terraform/
│   ├── ecs/                          # Terraform for ECS
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf                # Required outputs!
│   │   ├── dev.tfvars
│   │   ├── qa.tfvars
│   │   └── prod.tfvars
│   └── modules/                      # Terraform modules
├── Dockerfile
└── src/                              # Application source

Critical Terraform Outputs

Your Terraform code must export the required outputs based on deployment type:

For ECS Rolling Update:

output "ecs_cluster" {
  value = module.my_ecs_cluster.name
}

output "ecs_service" {
  value = module.my_ecs_service.name
}

output "task_definition_family" {
  value = module.my_task_definition.family
}

output "task_definition_tags_all" {
  value = module.ecs_task_definition.tags_all
}

For Blue-Green with CodeDeploy:

output "ecs_cluster" {
  value = module.my_ecs_cluster.name
}

output "ecs_service" {
  value = module.my_ecs_service.name
}

output "task_definition_family" {
  value = module.my_task_definition.family
}

output "codedeploy_application" {
  value = module.my_codedeploy_app.name
}

output "codedeploy_deployment_group" {
  value = module.my_codedeploy_app.deployment_group.deployment_group_name
}

output "appspec_file_arn" {
  sensitive = true
  value = module.my_appspec.arn
}

output "task_definition_tags_all" {
  value = module.ecs_task_definition.tags_all
}

Artifact Promotion

The workflow automatically handles artifact promotion from SaaS Artifactory:

  • Feature branches: Pull from <project-key>-docker-np-loc
  • Default branch/tags: Pull from <project-key>-docker-release-loc
  • artifact-environment: RELEASE: Use release repository
  • artifact-environment: CERTIFIED: Use certified repository

Best Practices

1. Container Image Management

  • Use semantic versioning for tags
  • Tag images with git SHA for traceability
  • Implement image scanning in CI pipeline
  • Use golden images as base images

2. Terraform Organization

  • Separate Terraform code by environment or service
  • Use modules for reusable infrastructure
  • Define all required outputs
  • Use .tfvars files for environment-specific values

3. Deployment Strategy

  • Use rolling updates for faster, simpler deployments
  • Use blue-green for zero-downtime critical services
  • Implement health checks in task definitions
  • Configure proper timeout values

4. Security

  • Never hardcode secrets in Terraform
  • Use PRM or Volcan for secret management
  • Implement least-privilege IAM roles
  • Enable encryption for sensitive data

5. Testing

  • Enable E2E tests for critical deployments
  • Use plan-only mode for PR validation
  • Test deployments in dev/qa before production
  • Implement smoke tests post-deployment

6. Monitoring

  • Enable CloudWatch logging
  • Set up alerts for deployment failures
  • Monitor ECS service health
  • Track deployment metrics

7. State Management

  • Use remote state backends
  • Enable state locking
  • Regular state backups
  • Separate state files by environment

Troubleshooting

Common Issues

1. Terraform Output Missing

Problem: Workflow fails with "Required output not found"

Solution:

  • Verify all required outputs are defined in outputs.tf
  • Check output names match expected format exactly
  • Ensure Terraform apply completed successfully

2. Container Image Pull Failure

Problem: ECS cannot pull container image

Solution:

  • Verify image exists in specified repository
  • Check ECR/Artifactory permissions
  • Confirm docker-tag is correct
  • Validate jfrog-project-key for SaaS Artifactory

3. OIDC Authentication Failure

Problem: Unable to assume AWS/Azure role

Solution:

  • Verify OIDC is configured in cloud account
  • Check role trust relationship includes GitHub OIDC
  • Confirm correct cloud-type is specified
  • Ensure workflow has id-token: write permission

4. CodeDeploy Deployment Failure

Problem: Blue-green deployment fails

Solution:

  • Verify CodeDeploy application and deployment group exist
  • Check appspec.json file is valid
  • Ensure proper ALB/NLB configuration
  • Review deployment logs in CodeDeploy console

5. State Lock Issues

Problem: "State is locked" error

Solution:

  • Wait for other operations to complete
  • Use terraform-ops workflow to force unlock
  • Check for stuck GitHub Actions workflows
  • Verify state backend connectivity

Support & Documentation


Last Updated: January 16, 2026
Status: ✅ Skill Complete
Maintained By: Platform Engineering Team

Related Assets