How to package a VueJS + NodeJS + MongoDB application in Docker.

How to package a VueJS + NodeJS + MongoDB application in Docker.
As mentioned in the previous article, I worked on various projects. The first few days in a new team usually go similarly: a backend developer teams up with me and performs magical actions to install and deploy the application. Docker is indispensable for frontend developers because the backend is often written in a wide range of stacks like PHP/Java/Python/C#, and the frontend doesn't need to distract the backend every time to set everything up and deploy. I only saw a Docker-Jenkins integration in one place with transparent deployment, logs, and integrated automated tests.

Many detailed articles have been written about Docker. This article will focus on deploying a Single Page Application using VueJS/Vue Router, with the server side as a RESTful API using NodeJS, and MongoDB as the database. Docker Compose is used to describe and launch several containerized applications.

Why use Docker

Docker allows you to automate the application deployment process. Developers no longer need to install programs manually or struggle with version incompatibilities on their machines. Just install Docker and type 1-2 commands in the console. It is easiest to do this on Linux.

Getting started

Installing Docker and Docker Compose

Folder structure

We create 2 folders for the client and server applications. The file with the .yml extension is the configuration Docker Compose, where the application containers are defined and linked.
docker-compose.yml:

version: "3"
services:
  mongo:
    container_name: mongo
    hostname: mongo
    image: mongo
    ports:
      - "27017:27017"
  server:
    build: server/
    #command: node ./server.js #here you can override CMD from Dockerfile in /server
    ports:
      - "3000:3000"
    links:
      - mongo
  client:
    build: client/
    #command: http-server ./dist #here you can override CMD from Dockerfile in /client
    network_mode: host
    ports:
      - "8089:8089"
    depends_on:
      - server

We create 3 services in Docker: for NodeJS, MongoDB, and static content on Vue. To link the client to the server, we added depends on server. To link MongoDB with the server API, we use links mongo. Server, client, mongo — these are the names of the services.

Client on VueJS

In the folder /client The application is located on VueJS. The application is created using Vue CLI. When building the image, the client application is compiled into a set of static files in the folder /dist. The Dockerfile describes the set of commands for building the image:

FROM node:10
WORKDIR /client
COPY ./package*.json ./
RUN npm install
RUN npm install -g http-server
COPY . .
RUN npm run build
EXPOSE 8081
CMD ["npm", "test:dev"]

Note that package.json is copied and installed separately from the other project files. This is done for performance, so that the contents of the /node_modules folder are cached on rebuilds. Each command line is cached separately.

At the end, when the container is launched, the command is executed npm run dev. This command is described in package.json:


"scripts": {
	 "test:dev": "http-server dist -p 8081 -c 1 --push-state"
}

To run files from the folder /dist, http-server is installed globally , and in dev-dependencies the packagespa-http-server , so that Vue Router works correctly. The --push-state flag redirects to index.html. The -c flag with a value of 1 second is added tonot cache scripts. This is a test example; for a real project, it’s better to use nginx. , and in dev-dependencies the package In the Vuex store, we create the field

apiHost: 'http://localhost:3000' , where the NodeJS API port is specified. The client side is ready. Now all requests from the client to the backend are directed to this URL.NodeJS server API

we create

In the folder /server and Dockerfile: server.js FROM node:10 WORKDIR /server COPY ./package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "server.js"]


for the database

In server.js states url const url = 'mongodb://mongo:27017/'; . We allow cross-origin requests from the client:const clientUrl = 'http://localhost:8081'; const corsOptions = { origin: clientUrl, optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204 }; app.use(cors()); app.all('/*', (req, res, next) => { res.header('Access-Control-Allow-Origin', clientUrl); res.header('Access-Control-Allow-Headers', 'X-Requested-With'); next(); }); app.get('/getProducts', cors(corsOptions), (req, res) => { products.getContent .then(data => res.json(data), err => res.json(err)); }); app.get('/getUsers', cors(corsOptions), (req, res) => { db.getUsers() .then(data => res.json(data), err => res.json(err)); });


Now let's go to the project directory and run

Conclusion

docker-compose build to build the images and docker-compose up to start the containers. This command will bring up 3 containers: server, client, mongo . For the server on NodeJS, you can set up hot-reload by linking it with the user folder. The client in development stage should be run locally with hot reload, launched separately. To start a separate service, just specify its name server and mongodocker-compose up client . Don't forget to occasionally doprune and delete containers, networks, and images to free up resources. You can view the complete code

. The project is still in development. hereThe application of machine learning at Mail.ru

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster