diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..ee6efd7b8 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,47 @@ +# .github/workflows/deploy.yml +name: Deploy Symfony App to ECS + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build and push Docker image + id: build-image + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: BalajiDeepthi + IMAGE_TAG: ${{ github.sha }} + run: | + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + + - name: Deploy to Amazon ECS + id: deploy-ecs + uses: aws-actions/amazon-ecs-deploy@v1 + with: + cluster: phpDemoECS + service: phpDemoApp + task-definition: task-definition.json + force-new-deployment: true + wait-for-service-stability: true + task-definition-template-json: task-definition.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..c27e9439d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# Dockerfile +FROM php:8.1-apache + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + git \ + zip \ + unzip \ + libzip-dev \ + && docker-php-ext-install zip pdo_mysql + +# Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Set working directory +WORKDIR /var/www/html + +# Copy application code +COPY . . + +# Install PHP dependencies +RUN composer install --no-interaction --prefer-dist --optimize-autoloader + +# Set permissions +RUN chown -R www-data:www-data /var/www/html/var && chmod -R 775 /var/www/html/var + +# Expose port 80 +EXPOSE 80 + +# Configure Apache (optional, if you need custom config) +# COPY apache2.conf /etc/apache2/sites-available/000-default.conf + +# Start Apache +CMD ["apache2-foreground"] \ No newline at end of file diff --git a/task-definition.json b/task-definition.json new file mode 100644 index 000000000..7a3f3004b --- /dev/null +++ b/task-definition.json @@ -0,0 +1,4 @@ +{ + "family": "symfony-app", + "containerDefinitions": [] +} \ No newline at end of file diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 000000000..6ed49d3be --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,262 @@ +# main.tf +provider "aws" { + region = "us-east-1" +} + +resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "public" { + vpc_id = aws_vpc.main.id + cidr_block = "10.0.1.0/24" + availability_zone = "us-east-1a" +} + +resource "aws_instance" "app" { + ami = "ami-0c55b159cbfafe1f0" # Example Ubuntu AMI + instance_type = "t2.micro" + subnet_id = aws_subnet.public.id + + user_data = <<-EOF + #!/bin/bash + # Install PHP, MySQL, Composer, etc. + sudo apt update + sudo apt install -y apache2 php libapache2-mod-php php-mysql mysql-client composer unzip git + # Copy and configure the Symfony application (done by the pipeline) + EOF + + vpc_security_group_ids = [aws_security_group.app.id] +} + +resource "aws_security_group" "app" { + vpc_id = aws_vpc.main.id + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["192.168.2.15/32"] # Restrict SSH access + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_db_instance" "db" { + allocated_storage = 20 + engine = "mysql" + engine_version = "8.0" + instance_class = "db.t2.micro" + name = "symfony_db" + username = "admin" + password = "password123" # Securely manage passwords + skip_final_snapshot = true + vpc_security_group_ids = [aws_security_group.db.id] +} + +resource "aws_security_group" "db" { + vpc_id = aws_vpc.main.id + + ingress { + from_port = 3306 + to_port = 3306 + protocol = "tcp" + security_groups = [aws_security_group.app.id] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_ecs_cluster" "cluster" { + name = "phpDemoECS" +} + +resource "aws_ecr_repository" "repository" { + name = "balajideepthi" +} + +resource "aws_ecs_service" "service" { + name = "phpDemoApp" + cluster = aws_ecs_cluster.cluster.id + task_definition = aws_ecs_task_definition.task.arn + desired_count = 1 + launch_type = "FARGATE" + network_configuration { + subnets = [aws_subnet.public.id] + security_groups = [aws_security_group.app.id] + } + + load_balancer { + target_group_arn = aws_alb_target_group.arn + container_name = "symfony-app" + container_port = 80 + } +} + +resource "aws_ecs_task_definition" "task" { + family = "symfony-app" + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = 256 + memory = 512 + execution_role_arn = aws_iam_role.ecs_task_execution_role.arn + container_definitions = jsonencode([ + { + name = "symfony-app", + image = "${aws_ecr_repository.repository.repository_url}:${var.image_tag}", + portMappings = [ + { + containerPort = 80, + hostPort = 80 + } + ], + environment = [ + { + name = "DATABASE_URL", + value = "mysql://admin:${var.db_password}@${var.db_endpoint}:3306/symfony_db?serverVersion=8.0" + } + ], + logConfiguration = { + logDriver = "awslogs", + options = { + "awslogs-group" : aws_cloudwatch_log_group.log_group.name, + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } + } + ]) +} + +resource "aws_security_group" "alb" { + name = "symfony-alb-sg" + description = "Security group for ALB" + vpc_id = aws_vpc.main.id + + ingress { + description = "Allow HTTP traffic" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + + +resource "aws_iam_role" "ecs_task_execution_role" { + name = "ecs-task-execution-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Effect = "Allow", + Principal = { + Service = "ecs-tasks.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_policy" "ecs_task_execution_policy" { + name = "ecs-task-execution-policy" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + Effect = "Allow", + Resource = "*" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "ecs_task_execution_policy_attachment" { + role = aws_iam_role.ecs_task_execution_role.name + policy_arn = aws_iam_policy.ecs_task_execution_policy.arn +} + +resource "aws_cloudwatch_log_group" "log_group" { + name = "/ecs/symfony-app" +} + +resource "aws_alb" "alb" { + name = "symfony-alb" + internal = false + load_balancer_type = "application" + security_groups = [aws_security_group.alb.id] + subnets = [aws_subnet.public.id] + tags = { + Environment = "production" + } +} + +resource "aws_alb_target_group" "target_group" { + name = "symfony-target-group" + port = 80 + protocol = "HTTP" + vpc_id = aws_vpc.main.id + target_type = "ip" + + health_check { + path = "/health" + protocol = "HTTP" + matcher = "200" + } +} + +resource "aws_alb_listener" "listener" { + load_balancer_arn = aws_alb.alb.arn + port = 80 + protocol = "HTTP" + + default_action { + target_group_arn = aws_alb_target_group.target_group.arn + type = "forward" + } +} + +output "alb_dns_name" { + value = aws_alb.alb.dns_name +} + +output "app_public_ip" { + value = aws_instance.app.public_ip +} + +output "db_endpoint" { + value = aws_db_instance.db.endpoint +}