CI/CD pipeline for Next.js applications using GitHub Actions and docker
In this blog, we will set up a CI/CD pipeline for Next.js applications using GitHub Actions and Docker. We will also deploy the application to digital ocean droplet.
Prerequisites
- A GitHub account
- A Next.js application
- A Digital Ocean account
- Docker installed on your local machine
- A Domain(optional)
I'll be using a sample Next.js application for this blog. we will gonna dockerize it and use docker hub to store the docker image. we will use GitHub actions to build the docker image and deploy it to the digital ocean droplet. It's a simple process and you can follow along. If you have any questions, feel free to ask in the comments.
Dockerize the Next.js application
First, we need to dockerize the Next.js application. Create a Dockerfile
in the root of your Next.js application and add the following content:
Dockerfile
FROM node:18-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=build /app/.next ./.next
COPY --from=build /app/package.json ./
COPY --from=build /app/public ./public
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
ENV NODE_ENV production
CMD ["npm", "start"]
This Dockerfile does the following:
- It uses the official Node.js image as a base.
- It sets the working directory inside the container.
- It copies the
package.json
andpackage-lock.json
files to the working directory. - It installs the dependencies.
- It copies the rest of the application to the working directory.
- It builds the Next.js application.
- It uses another stage for production to keep the image small.
- It sets the working directory in the new stage.
- It copies the built files from the build stage.
- It exposes the port that the Next.js app runs on.
- It sets the environment variable for production.
- It specifies the command to run the Next.js app.
Create a GitHub repository
Create a new GitHub repository for your Next.js application. You can do this by clicking on the "New" button on the GitHub homepage and following the instructions. Once you have created the repository, push your Next.js application code to the repository. You can do this by running the following commands in your terminal:
git remote add origin
git branch -M main
git push -u origin main
Set up Docker Hub
Next, we need to set up Docker Hub to store the Docker image. Create a Docker Hub account if you don't already have one. Once you have created the account, create a new repository for your Next.js application. You can do this by clicking on the "Create Repository" button on the Docker Hub homepage and following the instructions.
Build and push the Docker image
Build the Docker image for your Next.js application by running the following command in your terminal:
docker build -t my-app .
This command builds the Docker image with the tag my-app
. Next, push the Docker image to Docker Hub by running the following command in your terminal:
docker tag my-app:latest my-docker-username/my-app:latest
docker push my-docker-username/my-app:latest
Replace my-docker-username
with your Docker Hub username. This command tags the Docker image with your Docker Hub username and pushes it to Docker Hub.
Set up Digital Ocean droplet
Next, we need to set up a Digital Ocean droplet to deploy the Next.js application. Create a new droplet on Digital Ocean by following the instructions on the Digital Ocean website. Once you have created the droplet, SSH into the droplet and install Docker by running the following commands:
ssh root@your-droplet-ip
apt update
apt install docker.io
Replace your-droplet-ip
with the IP address of your Digital Ocean droplet. This command installs Docker on the droplet.
Set up GitHub Actions
Next, we need to set up GitHub Actions to build the Docker image and deploy it to the Digital Ocean droplet. Create a .github/workflows/main.yml
file in the root of your GitHub repository and add the following content:
main.yml
name: Deploy to DigitalOcean Droplet
on:
push:
branches:
- main # Adjust the branch as needed
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Log in to Docker Hub
run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin
- name: Build and Push Docker Image
run: |
docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/my-app .
docker tag ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest
- name: Set up SSH
uses: webfactory/ssh-agent@v0.5.3
with:
ssh-private-key: ${{ secrets.DIGITALOCEAN_SSH_KEY }}
- name: Add DigitalOcean Droplet to known_hosts
run: |
echo "${{ secrets.DROPLET_SSH_PUBLIC_KEY }}" >> ~/.ssh/known_hosts
- name: Deploy to DigitalOcean Droplet
run: |
ssh root@${{ secrets.DIGITALOCEAN_DROPLET_IP }} "docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest && docker ps -q | xargs -r docker stop && docker run -d -p 3000:3000 ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest"
You will need to add the following secrets to your GitHub repository:
DOCKER_HUB_USERNAME
: Your Docker Hub usernameDOCKER_HUB_PASSWORD
: Your Docker Hub passwordDIGITALOCEAN_SSH_KEY
: Your Digital Ocean SSH private keyDROPLET_SSH_PUBLIC_KEY
: Your Digital Ocean droplet SSH public keyDIGITALOCEAN_DROPLET_IP
: Your Digital Ocean droplet IP address
Understanding the GitHub Actions workflow
This GitHub Actions workflow does the following:
- It listens for pushes to the
main
branch. - It checks out the code from the repository.
- It sets up Docker Buildx for building multi-architecture images.
- It logs in to Docker Hub using the provided credentials.
- It builds the Docker image and pushes it to Docker Hub.
- It sets up SSH for connecting to the Digital Ocean droplet.
- It adds the Digital Ocean droplet to the known hosts.
- It deploys the Docker image to the Digital Ocean droplet.
Conclusion
In this blog, we set up a CI/CD pipeline for Next.js applications using GitHub Actions and Docker. We also deployed the application to a Digital Ocean droplet. This is a simple and effective way to automate the deployment process and ensure that your application is always up to date. If you have any questions or feedback, feel free to leave a comment below. Happy coding!