Как упаковать VueJS + NodeJS + MongoDB приложение в Docker

от автора

New-Project-1
Как можно понять из предыдущей статьи, я работала с разными проектами. Первые дни в новой команде обычно проходят одинаково: бэкендер подсаживается ко мне и выполняет магические действия по установке и деплою приложения. Докер незаменим для фронтендеров, т.к. бэкенд зачастую написан на широком спектре стеков PHP/Java/Python/C# и фронту не надо каждый раз отвлекать бэка, чтобы все установить и развернуть. Только в одном месте я видела связку Docker-Jenkins с прозрачным деплоем, логами, прикрученными автотестами.

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

Зачем нужен Докер

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

Getting started

Устанавливаем Docker and 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

В папке /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, запустив отдельно server и mongo. Чтобы запустить отдельный сервис, достаточно указать его имя docker-compose up client. Не забывайте иногда делать prune и удаление контейнеров (containers), сетей (networks) и образов (images), чтобы высвободить ресурсы.

Полный код можно посмотреть тут. Проект еще в стадии разработки.


ссылка на оригинал статьи https://habr.com/ru/post/476590/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *