In todayβs development landscape, containerization is revolutionizing how applications are built, shipped, and run. Tools like Docker simplify deployment, improve scalability, and ensure consistency across environments.
In this article, weβll explore how to use Docker to containerize a Next.js frontend and a Node.js backend, highlighting the many benefits Docker brings to modern development workflows. π³
We will use one of the app I developed for one of my previous guide:
Securing Your Fullstack App: Authentication & Authorization with JWT in Next.js and Node π π
Rodolphe Dupuis γ» Nov 27
Here we go! π
Why use Docker?
First of all, it's important to understand why we use this tool.
Docker provides several advantages for developers and businesses:
- Environment Consistency: Ensures your app runs identically on development, staging, and production environments.
- Simplified Deployment: Packaged containers make deployments repeatable and scalable.
- Dependency Management: Bundles dependencies into containers, eliminating "it works on my machine" issues.
- Scalability: Containers are lightweight and can be scaled horizontally with ease.
- Isolation: Containers keep your application isolated from the host system, improving security and stability.
Setting Up Docker for a Next.js and Node.js Application
Prerequisites
- Install Docker
- Basic understanding of Docker concepts
project/
βββ jwt-back/
β βββ package.json
β βββ server.js
β βββ Dockerfile
βββ jwt-front/
β βββ package.json
β βββ next.config.js
β βββ Dockerfile
βββ docker-compose.yml
Step 1: Containerize the Node.js Backend
We created this previous package.json
in the backend app:
{
"name": "jwt-back",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "Rodolphe Dupuis",
"license": "ISC",
"description": "",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.3",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"express": "^4.21.1",
"jsonwebtoken": "^9.0.2"
}
}
Let's add the Dockerfile:
# Use Node.js as the base image
FROM node:18
# Set the working directory
WORKDIR /app
# Copy the package.json file and install its dependencies
COPY package.json .
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the port the app will run on
EXPOSE 5001
# Start the server
CMD ["npm", "start"]
Now that we are all set with the backend Dockerfile, we can build and run it:
docker build -t backend-app ./backend
docker run -p 3001:3001 backend-app
So far everything looks good and the backend app is running smoothly.
Step 2: Containerize the Next.js Frontend
βοΈ We created this previous package.json
in the frontend app when creating the Next.js app:
{
"name": "jwt-front",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"axios": "^1.7.8",
"next": "15.0.3",
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106"
},
"devDependencies": {
"eslint": "^8",
"eslint-config-next": "15.0.3"
}
}
Let's add the Dockerfile:
# Use Node.js as the base image
FROM node:18
# Set the working directory
WORKDIR /app
# Copy package.json and install dependencies
COPY package.json .
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the app
RUN npm run build
# Expose the port for Next.js
EXPOSE 3001
# Start the app
CMD ["npm", "start"]
Now that we are all set with the frontend Dockerfile, we can build and run it:
docker build -t frontend-app ./frontend
docker run -p 3000:3000 frontend-app
At this step, your frontend app is running using Docker perfectly as well as your backend app
Step 3: Orchestrate with Docker Compose
Now, let's break into one of the most important and powerful part of Docker: orchestrating. Docker Compose simplifies the process of managing multi-container applications.
Let's add a docker-compose.yml
file at the root of the project (check the project structure again if needed):
version: '3.8'
services:
frontend:
build: ./jwt-front
ports:
- "3000:3000"
depends_on:
- backend
backend:
build: ./jwt-back
ports:
- "5001:5001"
Now, you can run the application with Docker Compose using the following command:
docker-compose up --build
Now you can freely access your frontend app at http://localhost:3000
and interact with the server!
Benefits of Using Docker for This Setup
We are almost at the end of this guide and maybe you are wondering what is the purpose behind all that. After all, you are still accessing your frontend app the same way right?
Let's break down the benefits of Docker:
Simplified Development Environment
Docker ensures that both the frontend and backend run in isolated, consistent environments, eliminating setup hassles.Portability
The entire application can be packaged and run on any machine with Docker, regardless of the host OS π¦Scalability
Using tools like Kubernetes, these containers can be easily scaled to handle high traffic π οΈEfficient Resource Usage
Containers are lightweight and start quickly, improving performance compared to traditional virtual machines πEase of Testing
Spin up identical containers for staging or testing without impacting the production environment π’Seamless Collaboration
Teams can share Docker images or configurations, ensuring everyone is working on the same environment π
Best Practices for Dockerizing Your App
You can use .dockerignore
to exclude unnecessary files from your image (e.g., node_modules
or .git
directories).
Keep Docker images lightweight by using multistage builds. Multistage builds make use of one Dockerfile with multiple FROM instructions. Each of these FROM instructions is a new build stage that can COPY artifacts from the previous stages.
Regularly update your base images to include the latest security patches.
Use environment variables for sensitive data, avoiding hardcoding them into Dockerfiles.
Conclusion
Implementing Docker for your Next.js and Node.js app brings reliability, scalability, and simplicity to your development workflow. By containerizing both the frontend and backend, you streamline deployment, maintain environment consistency, and unlock the potential for rapid scaling.
Docker is a must-have tool for modern developersβstart using it today and elevate your application development process! π
Let me know if there is a concept or tech that you would like me to talk about!
Happy coding!
Top comments (0)