Docker-First Approach: Streamlining Node.js and Vue.js Development in a mono repo.

Selva Prasath
5 min readJul 2, 2024

--

Introduction:

The area of focus of this article is about containerizing the frontend and backend applications and successfully running them using docker-compose. If you are looking for an article that discusses the orchestration and highly available deployments, it is currently on my pipeline.

What is a Monorepo?

A monorepo, short for monolithic repository, is a version control strategy where all the code for multiple projects, often related or interdependent, is stored in a single repository. This approach contrasts with a polyrepo, where each project is kept in its own separate repository. Monorepos facilitate easier code sharing, dependency management, and consistent versioning across projects.

Project Code structure

Microservices
|
| - services
| | - vue-app
| | | - src
| | | - DockerFile
| |
| | - login-service
| | | - src
| | | - DockerFile
|
| - package.json
| - docker-compose.yml
| - Readme.md

Frontend: services/vue-app

The front end is a Vue.js application. It features a landing page that displays the user’s email if they are signed in, or prompts them to sign in or sign up if they are not. Since the goal was to focus on containerization, no major pages or features are planned for this codebase.

Backend: services/login-service

The backend is an Express application. As mentioned earlier, this application has two major endpoints: one for handling POST requests and another for GET requests to check if the application is up and running.

Database: mongo

MongoDB has been used as the database solution for this implementation. If you have MongoDB installed locally, it should be sufficient for development. Alternatively, if you have a container running MongoDB, that will also work.

Alright, We have got a quick intro. Let’s gear up for the next set of tasks.

Containerization Journey

Each service is going to have a Docker file. A DockerFile is a text document that contains all the commands a user could call on the command line to assemble an image.

The below file is an example of containerizing a docker image for a vue js application.

# Use the lightweight node image from official Docker Hub
FROM node:18.18.0-alpine as build-stage
# set the working directory
WORKDIR /app
# Copy the package files to the working directory in the container
COPY package*.json .
# Install the project dependencies
RUN npm install
# Copy the rest of the project files to the container
COPY . .
# Build the Vue.js application to the production mode to dist folder
RUN npm run build
# Use the lightweight node image from the previous stage for production deployment
FROM node:18.18.0-alpine as production-stage
# set the working directory
WORKDIR /app
# Install http-server
RUN npm install -g http-server
# Copy the build files generated in the prev step to the current working directory
COPY --from=build-stage /app/dist /app
# Expose the port 8080
EXPOSE 8080
# Serve it from http-server
CMD ["http-server", "/app", "-p", "8080", "-c-1", "--proxy", "http://127.0.0.1:8080?"]
# --proxy - to handle routing correctly by serving index.html for all routes.
# -c-1: Disables caching by setting the cache TTL to -1

The below file is an example of containerizing a docker image for an express app.

# Use the lightweight node image from official Docker Hub
FROM node:18-alpine
# set the working directory
WORKDIR /usr/src/app
# Copy the package files to the working directory in the container
COPY package*.json ./
# Install the project dependencies
RUN npm install
# Copy the rest of the project files to the container
COPY . .
# Expose the port 3000
EXPOSE 3000
# run the start command to serve
CMD [ "npm", "start" ]

Now we have successfully created the DockerFile for both applications. That’s Great. Have we completed our goal?

Now that we have the DockerFile we can build and deploy our own services. But say I want a database associated with this express app which is not yet containerized as a part of these files. Now who is going to save me on this?

Docker Compose:

Docker compose says hi at this moment. Below is a docker-compose.yml file

version: "3.8"

services:
mongo:
image: mongo:latest
container_name: mongodb
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: rootPassword
login-service:
build:
context: ./services/login-service
container_name: login-service
environment:
- PORT=3000
- MONGO_URI=mongodb://root:rootPassword@mongo:27017/auth?authSource=admin
- JWT_SECRET=secretKey
ports:
- "3000:3000"
depends_on:
- mongo
vue-app:
build:
context: ./services/vue-app
container_name: vue-app
environment:
- VITE_LOGIN_SERVICE=http://localhost:3000/api/auth
ports:
- "8080:8080"

Version deals with the version number followed by the services.

There are three services listed as a part of this file.

  1. Mongo
  2. login-service
  3. vue-app

Mongo

Is it necessary to define a MongoDB instance? Not if you’re using MongoDB Atlas, as it eliminates the need for a local MongoDB service. However, for simplicity in my use case, I’ve included a MongoDB image for a container. This setup includes environment variables for the username and password, as well as configurations for the port, container image, and name.

login-service

The login-service uses the DockerFile under the services/login-service as an image, containername, followed by the environment variables needed and the port number to be exposed is being added. If you closely watch there is a depends attribute that mentions that this service depends on the mongo.

vue-app

The vue-app uses the DockerFile under the services/vue-app as an image, containername, followed by the environment variables needed and the port number to be exposed is being added

Docker Compose Commands

To build docker-compose file

docker compose build 

To run a docker-compose file

docker compose up

After successful completion. If you open your docker. you can see an image as below

Deployed application:

Opening the following would take you a page like below http://localhost:8080/

After successful registration and login, you will be able to see a screen like this.

Hurray you have successfully containerized an application and thats working perfectly.

Reminder

This application is to demonstrate how to deploy applications using Docker-Compose file hence error handling is not done in any extensive way. Unless your application is very simple and you aren’t worried about the high availability, orchestration holds good. In the upcoming article, we will explore deploying this with container orchestration tools available

If you would like to play around. The source code for this can be found here. Happy Learning

https://github.com/selvaprasath2706/Microservices

--

--