From 7c393cb5f3f35fb8506341ac24693bbde0b99f5b Mon Sep 17 00:00:00 2001 From: Nam Le Date: Sat, 21 Jun 2025 15:19:58 +0200 Subject: [PATCH] Fix CD pipeline --- .github/workflows/github_cd.yaml | 41 ++++++--------- compose.yaml | 2 +- ecs-infrastructure.yaml | 85 +++++++++++++++++++------------- src/chatbot/Dockerfile | 7 +-- ui/Dockerfile | 2 - 5 files changed, 71 insertions(+), 66 deletions(-) diff --git a/.github/workflows/github_cd.yaml b/.github/workflows/github_cd.yaml index 3c98749..22c0b85 100644 --- a/.github/workflows/github_cd.yaml +++ b/.github/workflows/github_cd.yaml @@ -51,45 +51,35 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 - uses: actions/setup-python@v3 - with: - python-version: "3.12" - - name: Install Hatch - run: | - python -m pip install --upgrade pip - pip install Hatch - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4.1.0 - 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: Build Docker images run: | - # Get the latest commit hash - GIT_COMMIT=$(git rev-parse --short HEAD) # Define public ECR repository URL PUBLIC_ECR_URL=public.ecr.aws/e7b5q5z5/nam685 # LangGraph API server - langgraph build -t chatbot -c langgraph.json - docker tag chatbot:latest $PUBLIC_ECR_URL/chatbot:$GIT_COMMIT + docker build -t chatbot -f src/chatbot/Dockerfile . + docker tag chatbot:latest $PUBLIC_ECR_URL/chatbot:${{ github.sha }} # API docker build -t chatbot-api -f api/Dockerfile . - docker tag chatbot-api:latest $PUBLIC_ECR_URL/chatbot-api:$GIT_COMMIT + docker tag chatbot-api:latest $PUBLIC_ECR_URL/chatbot-api:${{ github.sha }} # UI docker build -t chatbot-ui -f ui/Dockerfile ./ui - docker tag chatbot-ui:latest $PUBLIC_ECR_URL/chatbot-ui:$GIT_COMMIT + docker tag chatbot-ui:latest $PUBLIC_ECR_URL/chatbot-ui:${{ github.sha }} + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4.1.0 + 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: Log in to Amazon ECR run: | aws ecr-public get-login-password --region us-east-1 | \ - docker login --username AWS --password-stdin ublic.ecr.aws + docker login --username AWS --password-stdin public.ecr.aws - name: Push Docker images to ECR run: | PUBLIC_ECR_URL=public.ecr.aws/e7b5q5z5/nam685 - docker push $PUBLIC_ECR_URL/chatbot:$GIT_COMMIT - docker push $PUBLIC_ECR_URL/chatbot-api:$GIT_COMMIT - docker push $PUBLIC_ECR_URL/chatbot-ui:$GIT_COMMIT + docker push $PUBLIC_ECR_URL/chatbot:${{ github.sha }} + docker push $PUBLIC_ECR_URL/chatbot-api:${{ github.sha }} + docker push $PUBLIC_ECR_URL/chatbot-ui:${{ github.sha }} deploy-ecs-by-cloudformation: runs-on: ubuntu-latest @@ -107,4 +97,5 @@ jobs: uses: aws-actions/aws-cloudformation-github-deploy@v1 with: name: chatbot-ecs - template: ecs-infrastructure.yaml \ No newline at end of file + template: ecs-infrastructure.yaml + parameter-overrides: "GitCommitHash=${{ github.sha }}" \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index 34a7271..6642faa 100644 --- a/compose.yaml +++ b/compose.yaml @@ -39,7 +39,7 @@ services: environment: CONTAINER_PORT: 8000 REDIS_URI: redis://langgraph-redis:6379 - POSTGRES_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable + DATABASE_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable healthcheck: test: [ "CMD", "python", "src/chatbot/healthcheck.py" ] interval: 10s diff --git a/ecs-infrastructure.yaml b/ecs-infrastructure.yaml index ba0ca40..72701f5 100644 --- a/ecs-infrastructure.yaml +++ b/ecs-infrastructure.yaml @@ -16,6 +16,10 @@ Parameters: Description: Secret ARN for chatbot application Default: 'arn:aws:secretsmanager:eu-central-1:417744795771:secret:chatbot-secrets-TXOVcr' + GitCommitHash: + Type: String + Description: 'Git commit hash for Docker images' + Resources: # VPC and Networking VPC: @@ -161,23 +165,23 @@ Resources: - IpProtocol: tcp FromPort: 3000 ToPort: 3000 - SourceSecurityGroupId: !Ref ALBSecurityGroup + CidrIp: !Ref VpcCidr - IpProtocol: tcp FromPort: 8080 ToPort: 8080 - SourceSecurityGroupId: !Ref ECSSecurityGroup + CidrIp: !Ref VpcCidr - IpProtocol: tcp FromPort: 8000 ToPort: 8000 - SourceSecurityGroupId: !Ref ECSSecurityGroup + CidrIp: !Ref VpcCidr - IpProtocol: tcp FromPort: 5432 ToPort: 5432 - SourceSecurityGroupId: !Ref ECSSecurityGroup + CidrIp: !Ref VpcCidr - IpProtocol: tcp FromPort: 6379 ToPort: 6379 - SourceSecurityGroupId: !Ref ECSSecurityGroup + CidrIp: !Ref VpcCidr SecurityGroupEgress: - IpProtocol: -1 CidrIp: '0.0.0.0/0' @@ -186,7 +190,6 @@ Resources: EFSFileSystem: Type: AWS::EFS::FileSystem Properties: - CreationToken: chatbot-postgres-data FileSystemTags: - Key: Name Value: chatbot-postgres-data @@ -216,9 +219,8 @@ Resources: - IpProtocol: tcp FromPort: 2049 ToPort: 2049 - SourceSecurityGroupId: !Ref ECSSecurityGroup + CidrIp: !Ref VpcCidr - # IAM Roles ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: @@ -241,25 +243,18 @@ Resources: - secretsmanager:GetSecretValue Resource: !Ref SecretARN - # ECS Cluster ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: chatbot-cluster - CapacityProviders: - - EC2 - DefaultCapacityProviderStrategy: - - CapacityProvider: EC2 - Weight: 1 - # Auto Scaling Group for EC2 instances LaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: chatbot-ecs-lt LaunchTemplateData: - ImageId: ami-0c02fb55956c7d316 # Amazon Linux 2 ECS-optimized - InstanceType: t2.micro + ImageId: ami-0e6b9772c95871b64 + InstanceType: t3a.large IamInstanceProfile: Arn: !GetAtt EC2InstanceProfile.Arn SecurityGroupIds: @@ -278,14 +273,35 @@ Resources: LaunchTemplate: LaunchTemplateId: !Ref LaunchTemplate Version: !GetAtt LaunchTemplate.LatestVersionNumber - MinSize: 1 - MaxSize: 3 - DesiredCapacity: 1 + MinSize: 3 + MaxSize: 4 + DesiredCapacity: 3 Tags: - Key: Name Value: chatbot-ecs-instance PropagateAtLaunch: true + ECSCapacityProvider: + Type: AWS::ECS::CapacityProvider + Properties: + Name: chatbot-ec2-capacity-provider + AutoScalingGroupProvider: + AutoScalingGroupArn: !Ref AutoScalingGroup + ManagedScaling: + Status: ENABLED + TargetCapacity: 100 + ManagedTerminationProtection: DISABLED + + ECSClusterCapacityProviderAssociations: + Type: AWS::ECS::ClusterCapacityProviderAssociations + Properties: + Cluster: !Ref ECSCluster + CapacityProviders: + - !Ref ECSCapacityProvider + DefaultCapacityProviderStrategy: + - CapacityProvider: !Ref ECSCapacityProvider + Weight: 1 + EC2Role: Type: AWS::IAM::Role Properties: @@ -323,7 +339,7 @@ Resources: ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn ContainerDefinitions: - Name: postgres - Image: postgres:16 + Image: public.ecr.aws/docker/library/postgres:16 Memory: 512 Essential: true Environment: @@ -331,9 +347,8 @@ Resources: Value: postgres - Name: POSTGRES_USER Value: postgres - Secrets: - Name: POSTGRES_PASSWORD - ValueFrom: !Sub "${SecretARN}:POSTGRES_PASSWORD::" + Value: postgres MountPoints: - SourceVolume: postgres-data ContainerPath: /var/lib/postgresql/data @@ -357,7 +372,7 @@ Resources: Volumes: - Name: postgres-data EFSVolumeConfiguration: - FileSystemId: !Ref EFSFileSystem + FilesystemId: !Ref EFSFileSystem RedisTaskDefinition: Type: AWS::ECS::TaskDefinition @@ -369,7 +384,7 @@ Resources: ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn ContainerDefinitions: - Name: redis - Image: redis:6 + Image: public.ecr.aws/docker/library/redis:8 Memory: 256 Essential: true HealthCheck: @@ -399,16 +414,16 @@ Resources: ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn ContainerDefinitions: - Name: langgraph-api - Image: !Sub "${ECRRepositoryURI}/chatbot:latest" - Memory: 1024 + Image: !Sub "${ECRRepositoryURI}/chatbot:${GitCommitHash}" + Memory: 512 Essential: true Environment: - Name: CONTAINER_PORT Value: "8000" - Name: REDIS_URI Value: redis://redis.chatbot.local:6379 - - Name: POSTGRES_URI - Value: postgres://postgres:password@postgres.chatbot.local:5432/postgres?sslmode=disable + - Name: DATABASE_URI + Value: postgres://postgres:postgres@postgres.chatbot.local:5432/postgres?sslmode=disable - Name: LANGSMITH_TRACING Value: "true" - Name: LANGSMITH_PROJECT @@ -420,8 +435,8 @@ Resources: ValueFrom: !Sub "${SecretARN}:LANGSMITH_API_KEY::" - Name: OPENAI_API_KEY ValueFrom: !Sub "${SecretARN}:OPENAI_API_KEY::" - - Name: POSTGRES_PASSWORD - ValueFrom: !Sub "${SecretARN}:POSTGRES_PASSWORD::" + - Name: TAVILY_API_KEY + ValueFrom: !Sub "${SecretARN}:TAVILY_API_KEY::" HealthCheck: Command: - CMD-SHELL @@ -450,8 +465,8 @@ Resources: ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn ContainerDefinitions: - Name: fastapi - Image: !Sub "${ECRRepositoryURI}/chatbot-api:latest" - Memory: 512 + Image: !Sub "${ECRRepositoryURI}/chatbot-api:${GitCommitHash}" + Memory: 256 Essential: true Environment: - Name: CONTAINER_PORT @@ -488,8 +503,8 @@ Resources: ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn ContainerDefinitions: - Name: nextjs - Image: !Sub "${ECRRepositoryURI}/chatbot-ui:latest" - Memory: 512 + Image: !Sub "${ECRRepositoryURI}/chatbot-ui:${GitCommitHash}" + Memory: 256 Essential: true Environment: - Name: HOSTNAME diff --git a/src/chatbot/Dockerfile b/src/chatbot/Dockerfile index 2cd79eb..a1f2748 100644 --- a/src/chatbot/Dockerfile +++ b/src/chatbot/Dockerfile @@ -1,13 +1,13 @@ FROM langchain/langgraph-api:3.11-wolfi - +ENV POSTGRES_URL=postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB # -- Adding local package . -- ADD . /deps/chatbot # -- End of local package . -- # -- Installing all local dependencies -- -RUN PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -c /api/constraints.txt -e /deps/* +RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e /deps/* # -- End of local dependencies install -- ENV LANGSERVE_GRAPHS='{"chat": "/deps/chatbot/src/chatbot/graph.py:graph"}' @@ -15,12 +15,13 @@ ENV LANGSERVE_GRAPHS='{"chat": "/deps/chatbot/src/chatbot/graph.py:graph"}' # -- Ensure user deps didn't inadvertently overwrite langgraph-api RUN mkdir -p /api/langgraph_api /api/langgraph_runtime /api/langgraph_license && touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py -RUN PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir --no-deps -e /api +RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir --no-deps -e /api # -- End of ensuring user deps didn't inadvertently overwrite langgraph-api -- # -- Removing pip from the final image ~<:===~~~ -- RUN pip uninstall -y pip setuptools wheel && rm -rf /usr/local/lib/python*/site-packages/pip* /usr/local/lib/python*/site-packages/setuptools* /usr/local/lib/python*/site-packages/wheel* && find /usr/local/bin -name "pip*" -delete || true # pip removal for wolfi RUN rm -rf /usr/lib/python*/site-packages/pip* /usr/lib/python*/site-packages/setuptools* /usr/lib/python*/site-packages/wheel* && find /usr/bin -name "pip*" -delete || true +RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx # -- End of pip removal -- WORKDIR /deps/chatbot \ No newline at end of file diff --git a/ui/Dockerfile b/ui/Dockerfile index 618e1b5..6bec48e 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -47,8 +47,6 @@ ENV NODE_ENV=production RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs -COPY --from=builder /app/public ./public - # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./