Setting Up CI/CD on AWS
Learn how to set up Continuous Integration and Continuous Deployment (CI/CD) pipelines on AWS Elastic Beanstalk
Welcome to this step-by-step guide for setting up Continuous Integration and Continuous Deployment (CI/CD) pipelines on AWS Elastic Beanstalk. Whether you're a beginner or just looking for a straightforward walkthrough, this guide will help you implement CI/CD using two popular methods: GitHub Actions and AWS CodePipeline.
🕮 Content provided by DeployPRO - the easiest way to deploy apps on AWS, Azure and Digital Ocean
✅ Option #1: GitHub Actions, AWS ECR, and Elastic Beanstalk
Step 1: GitHub Repository Setup
- Create a GitHub Repository:
- Navigate to GitHub.
- Click on the "+" in the top right corner and select "New repository."
- Name your repository and follow the instructions to create it.
- Clone the Repository:
- Open a terminal and run this command
git clone https://github.com/your-username/your-repository.git && cd your-repository
Step 2: GitHub Actions Configuration
- Create GitHub Actions Workflow:
- Inside your repository, create a
.github/workflows
directory. - Create a YAML file (e.g.,
main.yml
).
- Inside your repository, create a
- Add GitHub Actions YAML Script:
- Copy and paste the following script into
main.yml
- Replace placeholders like
AWS_ACCESS_KEY
,AWS_SECRET_KEY
,AWS_REGION
, andAWS_ACCOUNT_ID
with your actual values.
- Copy and paste the following script into
name: Build and Deployment
on:
push:
branches:
- main
- dev
- staging
- test
jobs:
build-image:
name: Build Image
runs-on: ubuntu-latest
outputs:
ENVIRONMENT: ${{ steps.generate-env.outputs.ENVIRONMENT }}
APP_NAME: ${{ steps.repo-name.outputs.repository-name }}
IMAGE_TAG_NGINX: nginx-${{ steps.generate-env.outputs.ENVIRONMENT }}-${{ github.run_number }}
IMAGE_TAG_APP: app-${{ steps.generate-env.outputs.ENVIRONMENT }}-${{ github.run_number }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- uses: FranzDiebold/github-env-vars-action@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Get repository name
id: repo-name
uses: MariachiBear/get-repo-name-action@v1.2.0
with:
string-case: "lowercase"
- name: Generate Environment Name
id: generate-env
run: |
if [ "${GITHUB_REF##*/}" = "main" ]; then echo "ENVIRONMENT=prod" >> $GITHUB_OUTPUT; fi
if [ "${GITHUB_REF##*/}" = "dev" ]; then echo "ENVIRONMENT=dev" >> $GITHUB_OUTPUT; fi
if [ "${GITHUB_REF##*/}" = "staging" ]; then echo "ENVIRONMENT=staging" >> $GITHUB_OUTPUT; fi
if [ "${GITHUB_REF##*/}" = "test" ]; then echo "ENVIRONMENT=test" >> $GITHUB_OUTPUT; fi
- name: Build and push the image Application to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ steps.repo-name.outputs.repository-name }}
IMAGE_TAG: app-${{ steps.generate-env.outputs.ENVIRONMENT }}-${{ github.run_number }}
# ENVFILE: ${{ secrets.ENVFILE }}
run: |
echo "Build the application docker image"
echo ${{ secrets.ENVFILE }} >> .env
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
echo "Pushing the image to ECR..."
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Build and push the image Nginx to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ steps.repo-name.outputs.repository-name }}
IMAGE_TAG: nginx-${{ steps.generate-env.outputs.ENVIRONMENT }}-${{ github.run_number }}
run: |
echo "Build the nginx docker image"
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./nginx
echo "Pushing the image to ECR..."
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
deployment:
name: Deploy Application
runs-on: ubuntu-latest
needs: [build-image]
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Generate deployment package
run: |
cp docker-compose-template.yml docker-compose.editing.yml
sed -i 's/AWS_ACCOUNT_ID/'"${{ secrets.AWS_ACCOUNT_ID }}"'/g' docker-compose.editing.yml
sed -i 's/IMAGE_TAG_APP/'"${{ needs.build-image.outputs.IMAGE_TAG_APP }}"'/g' docker-compose.editing.yml
sed -i 's/IMAGE_TAG_NGINX/'"${{ needs.build-image.outputs.IMAGE_TAG_NGINX }}"'/g' docker-compose.editing.yml
sed -i 's/AWS_REGION/'"${{ secrets.AWS_REGION }}"'/g' docker-compose.editing.yml
sed -i 's/IMAGE_NAME/'"${{ needs.build-image.outputs.APP_NAME }}"'/g' docker-compose.editing.yml
mv docker-compose.editing.yml docker-compose.yml
cat docker-compose.yml
zip -r deploy.zip ./docker-compose.yml
- name: Deploy Docker images to EB
uses: einaregilsson/beanstalk-deploy@v20
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
application_name: ${{ needs.build-image.outputs.APP_NAME }}
environment_name: ${{ needs.build-image.outputs.APP_NAME }}-${{ needs.build-image.outputs.ENVIRONMENT }}
region: ${{ secrets.AWS_REGION }}
version_label: ${{ github.sha }}
deployment_package: deploy.zip
Step 3: Adding Secrets to Your GitHub Repository
- Create AWS Access Key and Secret Key:
- Go to the AWS Management Console.
- Navigate to "IAM" (Identity and Access Management).
- In the left sidebar, click on "Users" and then "Add user."
- Give your user a name, check "Programmatic access," and click "Next."
- Attach the
AWSElasticBeanstalk
,AmazonEC2ContainerRegistryFullAccess
,AmazonEC2FullAccess
,AmazonRDSFullAccess
,AWSCodePipeline_FullAccess
,IAMFullAccess
,IAMUserChangePassword
, andSecretsManagerReadWrite
policies. - Review and create the user. Save the Access Key ID and Secret Access Key.
- Add AWS Credentials as Secrets:
- In your GitHub repository, go to "Settings" -> "Secrets and Variables" -> "Actions" -> "New repository secret."
- Add
AWS_ACCESS_KEY
,AWS_SECRET_KEY
,AWS_REGION
, andAWS_ACCOUNT_ID
any other necessary secrets. - Provide the corresponding values for each secret.
- Click "Add secret" to save.
Step 4: AWS Elastic Beanstalk Configuration
- Go to the AWS Management Console
- Navigate to the AWS Management Console.
- Sign in to your AWS account.
- Click "Create a New Environment"
- In the AWS Management Console, locate the "Elastic Beanstalk" service.
- Click on "Create a new environment."
- Configure Environment
- Select "Web server environment" as your environment type.
- Enter a unique and meaningful "Application name."
- Choose a distinctive "Environment name."
- Configure Service Access
- In the "Service role" section, create a new service role or use an existing one.
- If creating a new role, Elastic Beanstalk will guide you through the process.
- Optional - Set Up Networking, Database, and Tags
- Navigate to the "Configure more options" section.
- Configure networking, including VPC, subnets, and security groups.
- Set up a database if required, choosing options like RDS.
- Add tags for better organization.
- Optional - Configure Instance Traffic and Scaling
- Navigate to the "Capacity" section.
- Configure instance type, number of instances, and scaling options based on your requirements.
- Optional - Configure Updates, Monitoring, and Logging
- Navigate to the "Configuration" section.
- Configure application updates, monitoring options, and logging settings as needed.
- Review
- Click "Create environment" after reviewing all your configurations.
- Wait for Elastic Beanstalk to provision resources and deploy the sample application.
Step 5: Create an Elastic Container Registry (ECR)
- Create an ECR Repository:
- Go to the AWS Management Console.
- Click "Create repository" and follow the steps to create an ECR repository.
- Note the ECR repository URI (e.g.,
your-aws-account-id.dkr.ecr.your-aws-region.amazonaws.com/your-ecr-repository
).
Step 6: Testing the CI/CD Pipeline
- Commit and Push Changes:
- Create a new file, make changes, or push an existing file to the main branch.
- Commit your changes to the GitHub repository.
- Push the changes to the main branch.
- Monitor GitHub Actions Workflow:
- Go to the "Actions" tab in your GitHub repository to monitor the workflow.
- Ensure each step executes successfully.
- Verify Deployment on AWS Elastic Beanstalk:
- Visit the Elastic Beanstalk environment in the AWS Management Console.
- Verify that the new version is deployed successfully.
✅ Option #2: CodeBuild, ECR, CodePipeline, and Elastic Beanstalk
Step 1: GitHub Repository Setup
- Create a GitHub Repository:
- Navigate to GitHub.
- Click on the "+" in the top right corner and select "New repository."
- Name your repository and follow the instructions to create it.
- Clone the Repository:
- Open a terminal and run this command
git clone https://github.com/your-username/your-repository.git && cd your-repository
Step 2: AWS CodeBuild Configuration
- Navigate to AWS CodeBuild:
- Go to AWS CodeBuild.
- Click "Create build project"
- Define Build Specifications:
- In your GitHub repository, create a
buildspec.yml
- Set environment variable in CodeBuild with this
AWS_REGION
,AWS_ACCOUNT_ID
,IMAGE_TAG
, andIMAGE_REPO_NAME
. - Set environment to Ubuntu, and managed image.
- Choose a compatible runtime version.
- In the "Buildspec" section, select "Use a buildspec file" and specify the location of your
buildspec.yml
.
- In your GitHub repository, create a
version: 0.2
phases:
pre_build:
commands:
- echo Logging into Amazon ECR...
- aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t app-$IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag app-$IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:app-$IMAGE_TAG
- docker build -t nginx-$IMAGE_REPO_NAME:$IMAGE_TAG ./nginx/
- docker tag nginx-$IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:nginx-$IMAGE_TAG
- cp docker-compose-template.yml docker-compose.editing.yml
- sed -i 's/AWS_ACCOUNT_ID/'$AWS_ACCOUNT_ID'/g' docker-compose.editing.yml
- sed -i 's/IMAGE_TAG_APP/'app-$IMAGE_TAG'/g' docker-compose.editing.yml
- sed -i 's/IMAGE_TAG_NGINX/'nginx-$IMAGE_TAG'/g' docker-compose.editing.yml
- sed -i 's/AWS_REGION/'$AWS_REGION'/g' docker-compose.editing.yml
- sed -i 's/IMAGE_NAME/'$IMAGE_REPO_NAME'/g' docker-compose.editing.yml
- mv docker-compose.editing.yml docker-compose.yml
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image app...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:app-$IMAGE_TAG
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:nginx-$IMAGE_TAG
artifacts:
files:
- docker-compose.yml
Step 3: AWS CodePipeline Configuration
- Navigate to AWS CodePipeline:
- Go to AWS CodePipeline.
- Click "Create pipeline."
- Connect your GitHub repository as the source.
- Define Stages and Actions:
- Configure stages (source, build, deploy).
- For source, choose GitHub.
- For build, use AWS CodeBuild and connect to your GitHub repository.
- For deploy, select Elastic Beanstalk.
- Set Up Artifacts:
- Define input and output artifacts for smooth pipeline flow.
Step 4: AWS Elastic Beanstalk Configuration
- Create an Elastic Beanstalk Environment:
- Go to AWS Elastic Beanstalk.
- Click "Create a new environment"
- follow the setup wizard.
- Choose a sample application or upload your code.
Step 5: Testing the CI/CD Pipeline
- Commit and Push Changes
- Add or modify files in your repository.
- Commit and push changes to the main branch.
- Monitor CodePipeline Execution
- Visit the CodePipeline dashboard.
- Monitor the pipeline stages for successful execution.
- Verify Deployment on AWS Elastic Beanstalk
- Check your Elastic Beanstalk environment for the latest deployment.
✅ Setup Load Balancer for Elastic Beanstalk
Step 1: Create an SSL Certificate in ACM
- Sign in to AWS Console
- Go to AWS Management Console.
- Sign in with your AWS account.
- In the AWS Management Console, search for "Certificate Manager" or find it in the "Security, Identity, & Compliance" section.
- Request a Certificate
- Click on the "Request a certificate" button.
- Enter the domain name (e.g.,
www.yourdomain.com
) and click "Next." - Choose a validation method (e.g., DNS validation) and follow the on-screen instructions to complete the validation.
- Wait for the certificate status to change to "Issued."
Step 2: Configure Elastic Beanstalk Environment
- Environment Configuration
- Open the environment and click `Configurations`
- In the "Configure more options" section, navigate to the "Load Balancer" settings.
- Make sure "Enable Load Balancer" is selected.
- Save the configuration.
Step 3: Configure SSL for Load Balancer
- Open Load Balancer Configuration
- After configuring the environment, go to the environment dashboard.
- Navigate to the "Configuration" tab.
- Add Listener
- Scroll down to the "Load Balancer" section and click "Modify."
- Add a listener for HTTPS (port 443).
- Select the ACM certificate you created.
- Update Environment
- Scroll down and click "Apply" to update the environment.
Step 4: Test the Setup
- Access Your Application
- Once the deployment is complete, access your application using the HTTPS URL (e.g.,
https://www.yourdomain.com
). - Ensure that your browser shows the padlock icon, indicating a secure connection.
- Once the deployment is complete, access your application using the HTTPS URL (e.g.,
✅ GitHub Actions vs. CodePipeline
GitHub Actions:
Pros:
- Seamless integration with GitHub repositories.
- Quick setup and configuration using YAML files.
- Free for public repositories.
Cons:
- Limited parallelism for free accounts.
- May require additional setup for complex workflows.
AWS CodePipeline:
Pros:
- Native AWS integration for a comprehensive CI/CD experience.
- Scalable and robust pipeline configuration.
- Supports a wide range of AWS services.
Cons:
- May involve more initial setup steps.
- Costs are associated with usage, but a free tier is available.
✅ Conclusion
In conclusion, both GitHub Actions and AWS CodePipeline offer powerful CI/CD capabilities. GitHub Actions excels in simplicity and GitHub integration, while AWS CodePipeline provides a more comprehensive, native AWS experience. The choice between them depends on your project's specific needs and your team's familiarity with each platform.
✅ Resources
For questions and product requests, feel free to contact AppSeed via email or Discord: