Introduction

Deploying an application to production goes far beyond writing code. It involves building, testing, packaging, and delivering software in a reliable and repeatable way.

In this article, I’ll show how to build a complete pipeline — from commit to deployment — using GitHub Actions for CI/CD, Terraform for Infrastructure as Code, and AWS (ECR, ECS Fargate) as the runtime platform.

The concept presented here is language agnostic — it works with any stack that runs inside a Docker container (Node.js, Go, Java, Python, etc.). For the practical examples, we’ll use .NET as a reference, but the workflows, Terraform infrastructure, and deployment flow remain the same regardless of the chosen technology.

The goal is to demonstrate how these tools connect together to create an automated workflow where a simple merge into the main branch results in a new version running in production without manual intervention.


Prerequisites

Before getting started, you need the following tools installed and configured:

ToolDescriptionInstallation Link
DockerTo build and run containersdocs.docker.com/get-docker
TerraformTo provision infrastructure as codedeveloper.hashicorp.com/terraform/install
AWS CLITo interact with AWS services via terminaldocs.aws.amazon.com/cli/latest/userguide/install-cliv2.html
GitFor source controlgit-scm.com/downloads
AWS AccountWith permissions to create resources (IAM, ECS, ECR)aws.amazon.com/free
GitHub AccountTo host the repository and run workflowsgithub.com

Note: For this article, you’ll also need the .NET SDK installed locally for development. If you are using another stack, replace it with the corresponding SDK (Node.js, Go, JDK, etc.). Another important point is that ECS was chosen instead of EKS or EC2 because of its simpler learning curve, lower management overhead, and reduced infrastructure costs for study purposes.


Architecture Overview

The complete workflow looks like this:

Developer → Feature Branch → Pull Request → Validation (CI)
                                            Merge into main
                                          Build & Push (CD)
                                         Deploy to ECS Fargate

Configuring IAM for Terraform

Before running any terraform apply, Terraform needs permissions to create AWS resources. To do this, we need an IAM user (or role) with the appropriate permissions and configure its credentials locally.

Creating an IAM User for Terraform

In the AWS Console (IAM > Users), create a dedicated Terraform user:

  1. Go to IAM > Users > Create User
  2. Name the user (example: terraform-deployer)
  3. Attach the required policies for the resources being created:
AmazonECS_FullAccess
AmazonEC2ContainerRegistryFullAccess
AmazonVPCReadOnlyAccess
IAMFullAccess
CloudWatchLogsFullAccess
AmazonS3FullAccess

Security note: In production environments, the ideal approach is to create a custom policy following the principle of least privilege, granting only the strictly necessary permissions. For learning purposes, the managed policies above simplify the setup.

  1. After creating the user, generate an Access Key (IAM > Users > Security credentials > Create access key)
  2. Select the Command Line Interface (CLI) use case

Configuring Local Credentials

With AWS CLI installed, configure your credentials:

aws configure

You’ll be prompted for:

AWS Access Key ID: AKIA...
AWS Secret Access Key: wJal...
Default region name: us-east-1
Default output format: json

This creates the ~/.aws/credentials file that Terraform automatically uses through the AWS provider. Once this is done, Terraform is authorized to provision the resources we’ll define next.