Table of contents
- ๐พ What is CI/CD?
- ๐พ Requirements for Setting up CI/CD
- ๐พ 1. Project Creation and Writing Test Code and Logic
- ๐พ 2. Dockerfile Configuration
- ๐พ 3. Issuing a Token for GitHub Container Registry
- ๐พ 4. Writing GitHub Actions Workflow
- ๐พ 5. Creating an AWS EC2 Instance
- ๐พ 6. Installing GitHub Actions Runner & Docker in the EC2 SSH Environment
- ๐พ Conclusion
I apologize for the inconvenience. I will continue in English.
๐พ What is CI/CD?
CI/CD stands for Continuous Integration/Continuous Deployment. It is the practice of automating the entire process from application development to deployment to create an efficient service environment.
CI (Continuous Integration): It involves regularly merging, building, and testing newly created and modified code.
CD (Continuous Deployment): It includes automating the process of setting up a deployable environment, including CI, and deploying the application.
The flow of CI/CD
Source code
Merge
Test
Build
Ready to Deploy
Automatic Deployment
๐พ Requirements for Setting up CI/CD
To set up CI/CD, you need the following:
Project creation and writing test code and logic.
Dockerfile configuration.
Issuing a token for using GitHub Container Registry.
Writing GitHub Actions Workflow.
Creating an AWS EC2 instance.
Installing GitHub Actions Runner & Docker in the EC2 SSH environment.
You can follow these steps to implement CI/CD in your project.
๐พ 1. Project Creation and Writing Test Code and Logic
Create a Nest.js project and write the API logic and test code. Ensure that all test cases pass successfully for the GitHub Actions to pass the tests.
๐พ 2. Dockerfile Configuration
Install and run Docker Desktop.
Create a
Dockerfile
with the following contents (ensure the filename is correct):
# Match the local node version
FROM node:16.16.0
# Create a working directory for executing commands
RUN mkdir /app
WORKDIR /app
# Add the entire project to the working directory
ADD . /app
# Install project dependencies
RUN npm install
# Build Nest.js
RUN npm run build
# Expose port 3000
EXPOSE 3000
# Start the server
ENTRYPOINT npm run start:prod
- Create a
.dockerignore
file to specify files or folders that are not required for the build process.
node_modules/
dist/
Build the Docker image with the command
docker build -t [image name] .
. Replace[image name]
with the desired name for your image.Run the container in the background with the command
docker run --name [container name] -d -p 3002:3000 [image name]
. Replace[container name]
with the desired name for your container. This command maps port 3002 on the host to port 3000 in the container.Access the API at
http://localhost:3002
to verify that it is running successfully.
By completing these steps, you have successfully created and run a container.
๐พ 3. Issuing a Token for GitHub Container Registry
What is GitHub Container Registry?
GitHub provides a service called GitHub "Package" Registry, which is a package storage service for GitHub. It allows GitHub users to store, share, and distribute packages among themselves.
GitHub "Container" Registry is an enhanced version of the Package Registry that focuses specifically on managing Docker images.
To use GitHub Container Registry, you need to generate a GitHub Access Token.
Click on the "Generate new token" button and enter the necessary details in the classic version.
Configure the token with the required permissions. You can refer to the image in the original post for an example.
Copy the generated token and keep it securely.
Go to your repository's Settings > Secrets and variables > Actions, and click on "New repository secret".
Enter
CODEBLUE_TOKEN
as the name and paste the copied token as the value.Save the secret.
You have successfully issued a token for GitHub Container Registry.
๐พ 4. Writing GitHub Actions Workflow
In your repository, create a directory named
.github/workflows
.Inside the
.github/workflows
directory, create a file namedci.yml
.Write the following code in the
ci.yml
file:
# Workflow title
name: CodeBLUE-CI-CD
# Define environmental variables used in main.yml
env:
DOCKER_IMAGE: ghcr.io/siwon-kim/vog-nest
DOCKER_CONTAINER: vog-nest-container
# Event
# When push or pull request driven on the main branch
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Define tasks when event driven
# Order: test -> build -> deploy
# Each job will be executed under the runner container
jobs:
# test code with Jest
test:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v3
- name: Setup node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'npm'
- name: Load env file
run: |
touch .env
echo "MODE=${{ secrets.MODE }}" >> .env
echo "PORT=${{ secrets.PORT }}" >> .env
echo "RDS_DB_NAME=${{ secrets.RDS_DB_NAME }}" >> .env
echo "RDS_HOSTNAME=${{ secrets.RDS_HOSTNAME }}" >> .env
echo "RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}" >> .env
echo "RDS_PORT=${{ secrets.RDS_PORT }}" >> .env
echo "RDS_USERNAME=${{ secrets.RDS_USERNAME }}" >> .env
- name: Install dependencies
run: npm install
- run: npm run test
# Docker image build
build:
# Test must be completed for Build to get started
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: |
image=moby/buildkit:v0.10.6
- name: login to ghcr
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.CODEBLUE_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v3
with:
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
# Deploy to AWS ec2
deploy:
# Build must be completed for Deploy to get started
needs: build
# execute job using runner where ec2 is installed
runs-on: [self-hosted, label-vog]
# login into Github container registry
steps:
- name: Login to ghcr
uses: actions/checkout@v3
- name: Setup docker build
id: buildx
uses: docker/setup-buildx-action@v2
- name: login to ghcr
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.CODEBLUE_TOKEN }}
- name: Run docker
run: |
touch .env
echo "MODE=${{ secrets.MODE }}" >> .env
echo "PORT=${{ secrets.PORT }}" >> .env
echo "RDS_DB_NAME=${{ secrets.RDS_DB_NAME }}" >> .env
echo "RDS_HOSTNAME=${{ secrets.RDS_HOSTNAME }}" >> .env
echo "RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}" >> .env
echo "RDS_PORT=${{ secrets.RDS_PORT }}" >> .env
echo "RDS_USERNAME=${{ secrets.RDS_USERNAME }}" >> .env
docker stop ${{ env.DOCKER_CONTAINER }} && docker rm ${{ env.DOCKER_CONTAINER }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run --env-file ./.env -d -p 80:3000 --name ${{ env.DOCKER_CONTAINER }} --restart always ${{ env.DOCKER_IMAGE }}:latest
Replace
your-container-image-name
inenv: IMAGE_NAME: your-container-image-name
with the desired name for your container image.Commit and push the changes to your repository.
By completing these steps, you have successfully written a GitHub Actions Workflow.
๐พ 5. Creating an AWS EC2 Instance
Go to the AWS Management Console and sign in to your AWS account.
Open the EC2 Dashboard.
Click on "Launch Instances" to create a new EC2 instance.
Choose an Amazon Machine Image (AMI) based on your requirements. For example, you can select an Amazon Linux 2 AMI.
Select an instance type that suits your needs.
Configure the instance details, such as the number of instances, network settings, and storage.
Add tags if required.
Configure security groups to allow inbound and outbound traffic. For this setup, you'll need to allow inbound traffic on port 22 (SSH) and port 3000 (for the Nest.js application).
Review the instance details and click on "Launch" to start the EC2 instance.
Select an existing key pair or create a new one to connect to the instance.
Launch the instance.
You have now created an AWS EC2 instance.
๐พ 6. Installing GitHub Actions Runner & Docker in the EC2 SSH Environment
Connect to your EC2 instance using SSH. You can use a terminal or SSH client for this step.
Install the GitHub Actions Runner by following the official documentation: https://docs.github.com/en/actions/hosting-your-own-runners.
Install Docker on the EC2 instance by following the official Docker documentation: https://docs.docker.com/engine/install/.
Once you have completed these steps, you will have installed GitHub Actions Runner and Docker in the EC2 SSH environment.
๐พ Conclusion
By following the steps outlined above, you can set up CI/CD using GitHub Actions, Docker, and an AWS EC2 instance. This setup allows for continuous integration, automated testing, and deployment of your Nest.js application.
Please note that these instructions provide a general overview, and you may need to adapt them based on your specific project requirements and infrastructure setup.