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

Как да опаковате приложение на VueJS + NodeJS + MongoDB в Docker
Както можете да разберете от предишната статия, работила съм с различни проекти. Първите дни в новия екип обикновено преминават по един и същ начин: бекенд разработчикът ми се присъединява и изпълнява магически действия по инсталирането и деплоя на приложението. Docker е незаменим за фронтенд разработчиците, тъй като бекендът често е написан на разнообразни стекове PHP/Java/Python/C# и фронтендът не трябва да отвлича вниманието на бекенда всеки път, за да инсталира и разгръща всичко. Само на едно място видях интеграция Docker-Jenkins с прозрачен деплой, логове и свързани автоматизирани тестове.

Написано е много за Docker. В тази статия ще се говори за разгръщането на Single Page Application, използваща VueJS/Vue Router, като сървърната част е във вид на RESTful API с NodeJS, а като база данни се използва MongoDB. За описанието и стартирането на няколко контейнера с приложения се използва Docker Compose.

Защо е необходим Docker

Docker позволява автоматизиране на процеса по разгръщане на приложението. Разработчикът вече не трябва самостоятелно да инсталира програми или да се бори с несъвместимости на версии на собствената си машина. Достатъчно е да инсталира Docker и да напише 1-2 команди в терминала. Най-удобно е да се прави това на Linux.

Започваме

Инсталираме 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 услуги в Docker: за NodeJS, MongoDB и за статични файлове на Vue. За да свържем клиента със сървъра, е добавено depends on server. За свързването на MongoDB с API на сървъра се използва links mongo. Сървър, клиент, 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, // някои стари браузъри (IE11, различни SmartTV) не работят с 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, стартирайки отделно сървер и mongo. За да стартирате отделна услуга, просто укажете името ѝ docker-compose up client. Не забравяйте понякога да правите prune и изтриване на контейнери (containers), мрежи (networks) и изображения (images), за да освободите ресурси.

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

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster