1. Introduction
This guide covers the process of deploying a Next.js application with a CI/CD pipeline, using Docker for containerization and GitHub Actions for automation. We’ll also configure NGINX as a reverse proxy, secure the app with SSL certificates, and deploy it using a custom domain.
Brief overview of the tools involved:
- Next.js: React-based framework for building web applications.
- Docker: Containerization tool for creating consistent environments.
- GitHub Actions: CI/CD automation tool.
- GitHub Packages: Package hosting service for Docker images.
- NGINX: Web server to serve the Next.js app as a reverse proxy.
- SSL: Securing the app using SSL certificates.
- Domain: Setting up a custom domain for the application.
2. Prerequisites
Before proceeding with the deployment, ensure you have the following:
- Knowledge of Docker: Basic understanding of Docker is required.
- GitHub repository: The Next.js application should be hosted in a GitHub repository.
- GitHub Packages: For storing and managing Docker images.
- Access to a server: A VPS or similar server where you will host your application.
- NGINX: Installed and configured as a reverse proxy on your server.
- Domain name: You should have already purchased a custom domain.
- SSL certificate: Obtain an SSL certificate (e.g., using Let’s Encrypt or a similar service).
3. Dockerize the Next.js Application
To ensure that your Next.js application can run consistently across different environments, you need to containerize it using Docker. This involves creating a Dockerfile, which defines the environment and instructions for building and running your application in a container.
Here I’m using business-model-canvas
application as example.
3.1 Create a Dockerfile:
In the root of your Next.js project, create a Dockerfile
that defines how to build and run your application.
FROM softeko/bmc-generator-base AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install -g [email protected] && \
npm install --omit-dev
COPY . .
RUN npm run build
RUN npx playwright install chromium
FROM softeko/bmc-generator-base
WORKDIR /app
COPY --from=builder /app .
COPY --from=builder /root/.cache/ms-playwright /root/.cache/ms-playwright
EXPOSE 5000
CMD ["npm", "start"]
3.2 Create a .dockerignore file:
In the root of your project, create a .dockerignore file to exclude unnecessary files from the Docker build context (e.g., node_modules, logs, etc.). This helps reduce the image size and build time.
.git
.next
.husky
.vscode
.gitignore
.dockerignore
public
README.md
Dockerfile
node_modules
npm-debug.log
3.3 Build the Docker image locally:
Once the Dockerfile is ready, build the Docker image by running the following command in your terminal:
docker image build -t bmc-generator:1.0 .
3.4 Run the Docker container:
After building the image, run the container to verify the application works as expected:
docker container run -d --name bmc-generator -p 5000:5000 bmc-generator:1.0
3.5 Verify the application:
Open a browser and navigate to http://localhost:5000
to check if your Next.js application is running inside the Docker container. If everything is ok then you can now proceed to set up CI/CD to automate the building and deployment process.
Optional:
Now you can make commit after adding Dockerfile
and .dockerignore
files. Example commit message Add Dockerfile and .dockerignore files
.
4. Add repository secrets & variables
Go the bmc-generator > Settings > Secrets and variables > Actions > Variables > New repository variable
and the following variables:
- ENV
- GHCR_PAT
- VPS_HOST
- VPS_PASSWORD
- VPS_USER
5. Setting up CI/CD with GitHub Actions
To automate the build and deployment process, we will use GitHub Actions to build a Docker image from the Next.js application and deploy it to a VPS server. The process will be triggered on each push to the main
branch.
5.1 GitHub Actions Workflow:
Create a .github/workflows/deploy.yml
file in your repository with the following content:
name: Build and Deploy Docker Image
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Checkout Code from Repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
install: true
- name: Create .env file
run: |
echo "${{ vars.ENV }}" > .env
- name: Log in to GitHub Container Registry
run: echo "${{ vars.GHCR_PAT }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: ghcr.io/bmc-business-model-canvas/bmc-generator:latest
deploy:
runs-on: ubuntu-22.04
needs: build
steps:
- name: Checkout Code from Repository
uses: actions/checkout@v3
- name: Install sshpass
run: sudo apt-get install -y sshpass
- name: Deploy Docker Container to VPS
env:
SSH_PASSWORD: ${{ vars.VPS_PASSWORD }}
run: |
sshpass -p $SSH_PASSWORD ssh -o StrictHostKeyChecking=no ${{ vars.VPS_USER }}@${{ vars.VPS_HOST }} << 'EOF'
docker login ghcr.io -u ${{ github.actor }} --password ${{ vars.GHCR_PAT }}
if [ "$(docker ps -q -f name=bmc-generator)" ]; then
docker container stop bmc-generator
fi
if [ "$(docker container ls -a -q -f name=bmc-generator)" ]; then
docker container rm bmc-generator
fi
docker image pull ghcr.io/bmc-business-model-canvas/bmc-generator
docker run -d --name bmc-generator -p 5000:5000 ghcr.io/bmc-business-model-canvas/bmc-generator
docker image prune -f
EOF
5.2 Workflow Explanation:
5.2.1 Build Job:
- Checkout Code: Fetch the repository’s code.
- Set up Docker Buildx: Prepares the environment for building and pushing Docker images.
- Create .env file: Creates a
.env
file using environment variables. - Log in to GitHub Container Registry: Authenticates to GitHub Packages.
- Build and Push Docker Image: Builds the Docker image using the Dockerfile and pushes it to the GitHub Container Registry.
5.2.2 Deploy Job:
- Install
sshpass
: Installssshpass
to facilitate SSH connections to the VPS. - Deploy Docker Container to VPS: SSH into the VPS, stop any existing containers, remove them, pull the latest image, run the new container, and clean up unused images.
With this workflow in place, the Docker image will be built and deployed to your VPS whenever there is a push to the main
branch.
6. Configure NGINX as a Reverse Proxy
Once your Docker container is running on the VPS, you need to configure NGINX as a reverse proxy to route traffic to your application on port 5000. Additionally, we’ll create a symbolic link to enable this configuration.
6.1 (Optional) Install NGINX:
If you don’t already have NGINX installed on your VPS, install it with the following commands:
sudo apt-get update
sudo apt-get install nginx
6.2 Create NGINX Configuration:
Create a new configuration file for your application. Use the nano editor to create the file:
sudo nano /etc/nginx/sites-available/bmc.softekocms.com
Add the following configuration according to you application:
server {
listen 80;
server_name bmc.softekocms.com www.bmc.softekocms.com;
location / {
proxy_pass http://localhost:5000;
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;
}
}
6.3 Create a Symbolic Link:
To enable this configuration, create a symbolic link from sites-available to sites-enabled:
sudo ln -s /etc/nginx/sites-available/bmc.softekocms.com /etc/nginx/sites-enabled/
6.4 Test NGINX Configuration:
Test if the NGINX configuration is valid by running:
sudo nginx -t
6.5 Reload NGINX:
After confirming the configuration is valid, reload NGINX to apply the changes:
sudo systemctl reload nginx
Now NGINX will forward requests from bmc.softekocms.com to your Docker container running the Next.js application on port 5000.
7. Setting Up SSL with Certbot
To secure your application with SSL, you can use Certbot to generate and manage SSL certificates from Let’s Encrypt. This section will guide you through setting up SSL using Python Certbot.
7.1 (Optional) Install Certbot:
If you don’t have Certbot installed, you can install the Python Certbot package with the following commands:
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
7.2 Obtain an SSL Certificate:
Run the following command to obtain an SSL certificate for your domain bmc.softekocms.com:
sudo certbot --nginx -d bmc.softekocms.com -d www.bmc.softekocms.com
Note: When running Certbot for the first time, you may be prompted to provide an email address for urgent renewal and security notices.
Certbot will automatically configure NGINX to use the SSL certificate. Follow the on-screen prompts to complete the process.
7.3 Reload NGINX:
After confirming the configuration is valid, reload NGINX to apply the changes:
sudo systemctl reload nginx
Your application is now secured with an SSL certificate, and all traffic to bmc.softekocms.com will be encrypted.