Як спакаваць VueJS + NodeJS + MongoDB прыкладанне ў Docker

Як спакаваць VueJS + NodeJS + MongoDB прыкладанне ў Docker
Як можна зразумець з папярэдняга артыкула, я працавала з рознымі праектамі. Першыя дні ў новай камандзе звычайна праходзяць аднолькава: бэкендэр падсаджваецца да мяне і выконвае магічныя дзеянні па ўстаноўцы і дэплою прыкладання. Докер незаменны для франтэндэраў, т.я. бэкэнд часцяком напісаны на шырокім спектры стэкаў PHP/Java/Python/C# і фронту не трэба кожны раз адцягваць бэка, каб усё ўсталяваць і разгарнуць. Толькі ў адным месцы я бачыла звязку Docker-Jenkins з празрыстым дэплоем, логамі, прыкручанымі аўтатэстамі.

Пра докер напісана шмат падрабязных артыкулаў. У гэтым артыкуле прамова пайдзе аб разгортванні Single Page Application з выкарыстаннем VueJS/Vue Router, серверная частка ў выглядзе RESTful API c NodeJS, а ў якасці базы дадзеных выкарыстоўваецца MongoDB. Для апісання і запуску некалькіх прыкладанняў-кантэйнераў выкарыстоўваецца Docker Compose.

Навошта патрэбен Докер

Докер дазваляе аўтаматызаваць працэс разгортвання прыкладання. Распрацоўніку больш не трэба самастойна ўсталёўваць праграмы, дужацца з несумяшчальнасцю версій на сваёй машыне. Дастаткова ўсталяваць Докер і ўбіць 1/2 каманды ў кансоль. Зручней за ўсё рабіць гэта на Linux.

Прыступаючы да працы

Усталёўваны Докер і Стварыць докер

Структура тэчак

Ствараем 2 тэчкі для кліенцкага і сервернага прыкладанняў. Файл з пашырэннем .yml - гэта канфіг Docker Compose, дзе вызначаюцца і звязваюцца кантэйнеры прыкладання.
Docker-compose.yml:

version: "3"
services:
  mongo:
    container_name: mongo
    hostname: mongo
    image: mongo
    ports:
      - "27017:27017"
  server:
    build: server/
    #command: node ./server.js #здесь можно перезаписать CMD из Dockerfile в /server
    ports:
      - "3000:3000"
    links:
      - mongo
  client:
    build: client/
    #command: http-server ./dist #здесь можно перезаписать CMD из Dockerfile в /client
    network_mode: host
    ports:
      - "8089:8089"
    depends_on:
      - server

Ствараем 3 сэрвісу ў докеры: для NodeJS, MongoDB і для статыкі на Vue. Каб звязаць кліент з серверам дададзена depends on server. Для лінкоўкі MongoDB з серверным API выкарыстоўваецца links mongo. Server, client, mongo - назвы сэрвісаў.

Кліент на VueJS

У тэчцы /client размешчана дадатак на VueJS. Прыкладанне створана з дапамогай Vue Cli. Пры пабудове выявы кліенцкае прыкладанне білдзіцца ў набор статычных файлаў у тэчцы /dist. У Dockerfile апісаны набор каманд для пабудовы выявы:

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"]

Звярніце ўвагу, што package.json капіюецца і ўстанаўліваецца асобна ад астатніх файлаў праекта. Гэта зроблена для прадукцыйнасці, каб змесціва тэчкі /node_modules закэшавалася пры паўторным білдзе. Кожны радок-каманда кэшуецца асобна.

У канцы, пры запуску кантэйнера выконваецца каманда npm run dev. Гэтая каманда апісана ў package.json:


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

Каб запусціць файлы з тэчкі /dist, глабальна усталёўваецца http-server, а ў dev-dependencies пакет spa-http-server, Каб Vue Router працаваў карэктна. Сцяг push-state робіць рэдырэкт на index.html. Сцяг -c са значэннем 1 секунда дададзены, каб http-server не кэшаваў скрыпты. Гэта тэставы прыклад, на рэальным праекце лепш выкарыстоўваць nginx.

Ва Vuex store ствараем поле apiHost: 'http://localhost:3000', дзе прапісваецца порт NodeJS Api. Кліенцкая частка гатова. Цяпер усе запыты з кліента на бэк ідуць на гэты url.

NodeJS server API

У тэчцы /server ствараем server.js і Dockerfile:


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

В server.js паказваецца URL-адрасы для базы дадзеных const url = 'mongodb://mongo:27017/';. Дазваляем кроссдоменные запыты з кліента:


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));
  });

Заключэнне

Цяпер пяройдзем у дырэкторыю праекта і запусцім docker-compose build працяг пабудовы вобразаў і docker-compose up для запуску кантэйнераў. Каманда падыме 3 кантэйнеры: server, client, mongo. Для сервера на NodeJS можна наладзіць hot-reload, звязаўшы яго з user тэчкай. А кліент у стадыі распрацоўкі запускаць лакальна з hot reload, запусціўшы асобна сервер и Монго. Каб запусціць асобны сэрвіс, дастаткова пазначыць яго імя docker-compose up client. Не забывайце часам рабіць prune і выдаленне кантэйнераў (containers), сетак (networks) і вобразаў (images), каб вызваліць рэсурсы.

Поўны код можна паглядзець тут. Праект яшчэ ў стадыі распрацоўкі.

Крыніца: habr.com

Дадаць каментар