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
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
-
Metadata Onboarding:
- Product must be onboarded to Dojo360 Metadata API
- OR local metadata file created
-
OIDC Configuration:
- Required when
cloud-typeis set toawsOptumorazureOptum - AWS OIDC setup: Configure OpenID Connect in AWS
- Azure OIDC setup: Configure Azure OIDC
- Required when
-
Infrastructure Setup:
- ECS cluster must exist (created via infrastructure workflow)
- Task definitions and services configured
- CodeDeploy application and deployment group (for blue-green)
-
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
| Input | Description | Example |
|---|---|---|
aide-id | AideId from https://aide.optum.com for metadata | <your-aide-id> |
cloud-type | Cloud platform for metadata fetching | awsOptum, awsChc20, azureOptum |
domain | Domain for metadata | <your-domain> |
environment | Target deployment environment | dev, qa, cert, prod |
team-name | Team name for metadata | <your-team-name> |
Common Optional Inputs
| Input | Description | Default | Example |
|---|---|---|---|
artifact-environment | Source artifact environment for promotion | '' | RELEASE, CERTIFIED |
comment-on-pr | Comment Terraform plan output on PR | false | true |
container-registry | Cloud-specific container registry (ECR/ACR) | '' | <account>.dkr.ecr.us-east-1.amazonaws.com |
deployment-controller-type | Deployment strategy type | ECS | CODE_DEPLOY, MULTI_SERVICES_CODE_DEPLOY, batch-job |
docker-image | Fully qualified image path | '' | /repo-name/image-name |
docker-repository | Docker registry URL | docker.repo1.uhc.com | centraluhg.jfrog.io, artifactory.healthcareit.net |
docker-tag | Image tag to deploy | '' | latest, v1.0.0, pr-123 |
e2e-tests-enabled | Enable E2E tests after deployment | false | true |
e2e-workflow-file | E2E workflow file to execute | '' | .github/workflows/e2e-tests.yml |
e2e-workflow-inputs | JSON input overrides for E2E workflow | '' | {"environment": "qa"} |
jfrog-project-key | JFrog SaaS Artifactory project key | '' | your-project-docker-vir |
jfrog-release-bundle-name | Release bundle name for promotion | '' | your-app-v1.0.0 |
remote-state-file-name | Terraform remote state file name | '' | terraform.tfstate |
remote-state-folder-name | Terraform remote state folder | '' | container-infra |
run-plan-only | Only run terraform plan (no apply) | false | true |
runner-labels | Custom runner labels | '' | uhg-runner,docker |
terraform-directory | Path to Terraform code | . | terraform/ecs |
terraform-logging | Terraform log level | off | trace, debug, info |
terraform-prm-secrets | Comma-separated PRM secrets to map | '' | DB_PASSWORD,API_KEY |
terraform-vars-files | Comma-separated tfvars files | '' | dev.tfvars,common.tfvars |
terraform-vars-values | Inline Terraform variables | '' | instance_count=3,enable_logging=true |
terraform-version | Terraform version to use | ~> 1.9 | 1.9.5 |
volcan-decrypt-secrets | Decrypt secrets from Volcan | false | true |
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_clusterecs_servicetask_definition_familytask_definition_tags_all
2. CODE_DEPLOY (Blue-Green)
- AWS CodeDeploy blue-green deployment
- Traffic shifting strategies
- Automatic rollback on failure
Required Terraform Outputs:
ecs_clusterecs_servicetask_definition_familycodedeploy_applicationcodedeploy_deployment_groupappspec_file_arntask_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_definitionjob_queuecontainer_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: writepermission
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
- Sample Applications: pipelines-container-sample-apps
- Infrastructure Workflow: infrastructure.yml skill
- CI Workflows: ci-workflows-demos
- CloudBricks Documentation: pipelines-workflows/learn
- Supported Cloud Types: supported-clouds.md
- SaaS Artifactory: Enterprise Registry Documentation
Last Updated: January 16, 2026
Status: ✅ Skill Complete
Maintained By: Platform Engineering Team
Related Assets
github-workflows-dojo360-azure-infrastructure
Deploy Azure infrastructure using Terraform with PCAM vaulted access and native Azure authentication through Dojo360 Azure Infrastructure workflow
Owner: pcorazao
github-workflows-dojo360-container-promotion
Multi-environment container deployment promotion through prescribed deployment paths with automated approval gates and E2E testing
Owner: pcorazao
github-workflows-dojo360-database
Automate database schema updates using Liquibase via the Dojo360 database workflow (with rollback and validation patterns)
Owner: pcorazao
github-workflows-dojo360-database-promotion
Promote Liquibase database changes across environments (dev→qa→cert→prod) with deployment-path validation and approval gates
Owner: pcorazao
github-workflows-dojo360-dockerfile-ci
Build and scan container images from a Dockerfile using Optum golden images and the recommended UHG reusable workflow
Owner: pcorazao
github-workflows-dojo360-dotnet-ci
Build, test, and scan .NET apps using the recommended UHG reusable CI workflow, with optional publish/pack and container builds
Owner: pcorazao

