Як упакувати 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.

Приступаючи до роботи

Встановлюємо Docker та Docker compose

Структура папок

Створюємо 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

В папці /клієнт розташований додаток на VueJS. Додаток створено за допомогою Vue Cli. При побудові образу клієнтська програма білдится в набір статичних файлів у папці /розст. У 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"
}

Щоб запустити файли з папки /розст, глобально встановлюється http-server, а в dev-dependencies пакет spa-http-serverщоб Vue Router працював коректно. Прапор push-state робить редирект на index.html. Прапор -c зі значенням 1 секунда доданий, щоб http-сервер не кешував скрипти. Це тестовий приклад, що на реальному проекті краще використовувати 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

Додати коментар або відгук