Today, I tackled the process of Dockerizing a Node.js application, an essential skill in the DevOps toolkit.
Dockerization allows for consistent environments across various stages of development, testing, and production,
ensuring that applications run smoothly regardless of where they are deployed. However, this journey wasn't without its challenges!
Steps Taken
1. Setting Up the Project Directory:
First, I created a new directory for my Node.js application.
mkdir day6docker
cd day6docker
2. Initializing the Node.js Project:
Next, I initialized a new Node.js project and set up a basic Express server.
npm init -y
Created a server.js
file:
const express = require("express");
const path = require("path");
const axios = require("axios");
const morgan = require("morgan");
const app = express();
const morganMiddleware = morgan(
":method :url :status :res[content-length] - :response-time ms",
{
stream: {
write: message => console.log(message.trim()),
},
}
);
app.use(morganMiddleware);
app.use(express.static(path.join(__dirname, "public")));
app.set("view engine", "pug");
async function getRandomJoke() {
const response = await axios.get("https://api.chucknorris.io/jokes/random");
return response.data;
}
app.get("/", async (req, res, next) => {
try {
const response = await getRandomJoke();
res.render("home", {
title: "Random Chuck Norris Jokes",
joke: response,
});
} catch (err) {
next(err);
}
});
app.get("/joke", async (req, res, next) => {
try {
const response = await getRandomJoke();
res.json(response);
} catch (err) {
next(err);
}
});
app.use(function (err, req, res, next) {
console.error(err);
res.set("Content-Type", "text/html");
res.status(500).send("<h1>Internal Server Error</h1>");
});
const server = app.listen(process.env.PORT || 4000, () => {
console.log(`chucknorris server started on port: ${server.address().port}`);
});
function cleanupAndExit() {
server.close(() => {
console.log("chucknorris server closed");
process.exit(0);
});
}
process.on("SIGTERM", cleanupAndExit);
process.on("SIGINT", cleanupAndExit);
Installed Express:
npm install express
3. Creating a Dockerfile:
I then created a Dockerfile to define the image.
# Use the official Node.js image.
FROM node:14
# Create and change to the app directory.
WORKDIR /app
# Copy application dependency manifests to the container image.
COPY package*.json ./
# Install dependencies.
RUN npm install
# Copy local code to the container image.
COPY . .
# Run the web service on container startup.
CMD [ "node", "server.js" ]
# Inform Docker that the container listens on the specified network ports at runtime.
EXPOSE 3000
4. Building the Docker Image:
With the Dockerfile set up, I built the Docker image.
docker build -t my-node-app .
5. Running the Docker Container:
Finally, I ran the Docker container.
docker run -d -p 3000:3000 my-node-app
Challenges and Solutions
Challenge 1: Dependency Issues
Initially, I faced issues with my Node modules. My PowerShell commands weren't recognized properly. To resolve this, I used the following commands to clean up my environment and reinstall dependencies:
Remove-Item -Recurse -Force .\node_modules
Remove-Item -Force .\package-lock.json
npm install
When faced with vulnerabilities, I used:
npm audit fix
npm audit fix --force
Challenge 2: Image Not Found and Authorization Errors
When running the Docker container, I encountered errors indicating that the image wasn't found locally and pull access was denied.
To fix this, I either had to build the image from the Dockerfile or pull it from a repository:
Option A: Build the Image
docker build -t my-node-app .
Option B: Pull the Image
docker pull <username>/my-node-app:latest
Challenge 3: Docker Container Issues
On running the container, it initially failed to start. Checking the logs showed a missing module error. This was solved by ensuring all necessary files were included in the Docker context and correctly referenced.
Conclusion
Dockerizing an application, while challenging at times, is incredibly rewarding. It ensures that your application can run anywhere, from a local machine to a production server, with the same environment and dependencies. Mastering this skill is a significant step in the journey towards becoming a proficient DevOps engineer.
See you on Day 7 in a bit β it's not easy, but we move!
Top comments (0)