TL;DR
In this tutorial, you'll learn how to deploy your first javascript application on Kubernetes - a container orchestration platform βΈοΈ.
We will deploy a simple express server that returns a sample JSON object on Kubernetes locally using Minikube β¨.
Prerequisites π:
- Docker: For containerizing the application. π
- Minikube: For running Kubernetes locally. βΈοΈ
Odigos - Open-source Distributed Tracing
Monitor all your apps simultaneously without writing a single line of code!
Simplify OpenTelemetry complexity with the only platform that can generate distributed tracing across all your applications.
We are really just starting out.
Can you help us with a star? Plz? π½
Let's set it up π
We'll start by initializing our project with:
npm init -y
This initializes a NodeJS project with the package.json
π file which keeps track of our installed dependencies.
Install Express.js framework
npm install express
Now, inside the package.json
the dependencies object should look something like this. β
"dependencies": {
"express": "^4.18.2"
}
Now, at the root of the project create an index.js
file and add the following lines of code. π
// ππ» Initialize express.
const express = require("express");
const app = express();
const port = 3000;
// ππ» Return a sample JSON object with a message property on the root path.
app.get("/", (req, res) => {
res.json({
message: "Hello from Odigos!",
});
});
// ππ» Listen on port 3000.
app.listen(port, () => {
console.log(`Server is listening on port ${port}`);
});
We need to add a script in our package.json
for running the application. Add it within the scripts object of package.json
.
"scripts": {
"dev": "node index.js"
},
Now, to check our application is running properly, run the server using npm run dev
and make a get request to localhost:3000
either via CLI or in the browser. β¨
If you are using CLI, make sure to have cURL installed. β
curl http://localhost:3000
You should see something like this. ππ»
Now, you can simply stop the running express server using Ctrl + C
π«
Our sample application is ready! π Now, let's containerize it and push it to Kubernetes. π³βΈοΈ
Containerize the application π¦
We will be using Docker to containerize our application.
In the root of the project, create a new file named Dockerfile
.
π‘ Make sure to exactly name it the same. Otherwise, you will need to explicitly pass the
-f
flag for specifying theDockerfile
path.
# Uses node as the base image
FROM node:21-alpine
# Sets up our working directory as /app inside the container.
WORKDIR /app
# Copyies package json files.
COPY package.json package-lock.json ./
# Installs the dependencies from the package.json
RUN npm install --production
# Copies current directory files into the docker environment
COPY . .
# Expose port 3000 as our server uses it.
EXPOSE 3000
# Finally runs the server.
CMD ["node", "index.js"]
Now, we need to build βοΈ this container to be able to actually use it and push it to Kubernetes.
Run this command to build the Dockerfile
.
π¨ If you are running it on Windows, make sure to have Docker Desktop running.
// ππ» We are tagging our image name to express-server
docker build -t express-server .
Now, it's time to run the container. ππ»ββοΈπ¨
docker run -dp 127.0.0.1:3000:3000 express-server
π‘ We are running our container in the background with the container port 3000 mapping to our computer port 3000.
Once again run the following command and you should see the same result as earlier. β
curl http://localhost:3000
NOTE: This time the application is not running on our computer as before. Instead, it is running inside the container. π€―
Deploying in Kubernetes β
As said earlier, we will use Minikube to create an orchestration environment in our local computer and use kubectl
command to interact with Kubernetes. π
Start Minikube: π
minikube start
Since we are going to be using local containers instead of pulling them from the docker hub, run these commands. β¨
eval $(minikube docker-env)
docker build -t express-server .
eval $(minikube docker-env)
: It is used to point your terminalβs docker-cli
to the Docker Engine inside minikube.
π¨ Note, many of us use Fish as our shell, so for fish the corresponding command would be
eval (minikube docker-env)
Now, in the project root, create a nested folder k8/deployment
, and inside the deployment folder, create a new file called deployment.yaml
with the following content.
In this file, we will manage the deployment of our container. ππ»
# ππ» /k8/deployment/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: express-deployment
spec:
selector:
matchLabels:
app: express-svr
template:
metadata:
labels:
app: express-svr
spec:
containers:
- name: express-svr
image: express-server
imagePullPolicy: Never # Make sure to set it to Never, or else it will pull from the docker hub and fail.
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 3000
Finally, run this command to apply the deployment configuration we just created, deployment.yaml
. β¨
kubectl apply -f .\k8\deployment\deployment.yaml
Now, if we take a look at the running pods we can see that the pod has successfully been created. π
To view the logs of our created pod, run kubectl logs <pod_name>
and we should see the following.
With this, our express-server
is successfully deployed on a local Kubernetes. π
That is it for this article, we successfully containerized our application and deployed it to Kubernetes.
The source code for this article can be found here
https://github.com/keyval-dev/blog/tree/main/js-on-k8s
Thank you so much for reading! ππ«‘
Top comments (6)
Great guide!
COPY . .
Is a very bad idea as you copy too much of your project into the container. e g. All . files like .git .vscode are copied to the docker container and lead to size and security concernes.
You should ONLY copy what's really needed.
Thanks for the guide. You are running containers as root (not recommended), instead you can create a USER and start the process :)
Yes. It run as root but not like root as the underlying host.U can say it like shadow of root with limited privileges. U can add previlage using cap flag. If u want the container run as root as the underlying host u need to specify --previlaged flag along with the docker commands.
Great!!!
Great read! π₯ I am always amazed by how good Kubernetes is! π