In modern web development, setting up an efficient CI/CD pipeline for deploying your Angular applications can significantly enhance your workflow. This blog post guides you through setting up a GitHub Actions pipeline to build and deploy an Angular application using Docker, Nginx, and ensuring basic security group configurations in EC2.
Prerequisites
- A GitHub repository containing your Angular application.
- Docker installed on your local machine.
- GitHub Container Registry (GHCR) for storing Docker images.
- An EC2 instance or any server with Docker and Nginx installed.
- Proper security group settings on your EC2 instance.
Step 1: Modify Dockerfile to Accept Build Arguments
First, we need to update our Dockerfile to accept build arguments that specify the Angular environment. This ensures that our build process can dynamically adjust based on the environment.
# Use the official Node.js image as a base
FROM node:14
# Create and set the working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application files
COPY . .
# Set the environment variable to increase memory limit
ENV NODE_OPTIONS=--max_old_space_size=4096
# Build the Angular application based on the provided environment
ARG ANGULAR_ENV=production
RUN npm run build -- --configuration=$ANGULAR_ENV
# Expose the port the app runs on
EXPOSE 80
# Command to run the application
CMD ["npm", "start"]
Step 2: Set Up GitHub Actions Workflow
Next, we'll configure a GitHub Actions workflow to handle the build and deployment process.
name: Build and Deploy Angular
on:
push:
branches:
- main # Change this to your main branch name
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} # Use GitHub token secret
- name: Extract Git Commit Hash
id: vars
run: echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Build Docker Image
run: |
docker build --build-arg ANGULAR_ENV=production -t ghcr.io/yourusername/angular-docker:${{ env.COMMIT_HASH }} .
- name: Push Docker Image to GitHub Container Registry
run: |
docker push ghcr.io/yourusername/angular-docker:${{ env.COMMIT_HASH }}
- name: SSH and Deploy to Server
env:
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} # This is the private key secret for SSH
COMMIT_HASH: ${{ env.COMMIT_HASH }}
run: |
echo "$PRIVATE_KEY" > private_key.pem
chmod 600 private_key.pem
ssh -o StrictHostKeyChecking=no -i private_key.pem ubuntu@your-ec2-instance <<EOF
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker pull ghcr.io/yourusername/angular-docker:${COMMIT_HASH}
docker stop angular-app || true
docker rm angular-app || true
docker run -d --name angular-app -p 8080:80 ghcr.io/yourusername/angular-docker:${COMMIT_HASH}
sudo systemctl restart nginx
docker system prune -a -f --volumes
EOF
rm -f private_key.pem
permissions:
contents: read
packages: write
id-token: write
Step 3: Nginx Configuration
Update your Nginx configuration to correctly proxy requests to the Docker container.
server {
if ($host = yourdomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name yourdomain.com;
return 404;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # managed by Certbot
}
Step 4: EC2 Security Group Configuration
Ensure your EC2 instance's security group allows inbound traffic on ports 80 and 443.
- Log in to AWS Management Console.
- Navigate to EC2 Dashboard.
- Select Security Groups under "Network & Security".
- Find and Select Your Security Group associated with your EC2 instance.
-
Edit Inbound Rules to allow traffic on ports 80 (HTTP) and 443 (HTTPS):
-
HTTP (port 80):
- Type: HTTP
- Protocol: TCP
- Port Range: 80
- Source: 0.0.0.0/0
-
HTTPS (port 443):
- Type: HTTPS
- Protocol: TCP
- Port Range: 443
- Source: 0.0.0.0/0
- Login ghcr.io to pull the iamges from your github
-
HTTP (port 80):
export CR_PAT=YOUR_TOKEN
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
Summary
This setup ensures that:
- Each deployment uses a Docker image tagged with the specific Git commit hash.
- Unused Docker images are removed from your server to free up space.
- Your server runs the latest Docker image without accumulating old images.