Как Π΄Π° ΠΎΠΏΠ°ΠΊΠΎΠ²Π°Ρ‚Π΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ 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 ΠΈ 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. 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, // някои стари Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ΠΈ (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, ΠΊΠ°Ρ‚ΠΎ сС пуснС ΠΎΡ‚Π΄Π΅Π»Π½ΠΎ server ΠΈ mongo. Π—Π° Π΄Π° стартиратС ΠΎΡ‚Π΄Π΅Π»Π΅Π½ сСрвис, просто Π·Π°Π΄Π°ΠΉΡ‚Π΅ ΠΈΠΌΠ΅Ρ‚ΠΎ ΠΌΡƒ docker-compose up client. НС забравяйтС понякога Π΄Π° ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ prune ΠΈ Π΄Π° ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Ρ‚Π΅ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΈ (containers), ΠΌΡ€Π΅ΠΆΠΈ (networks) ΠΈ ΠΎΠ±Ρ€Π°Π·ΠΈ (images), Π·Π° Π΄Π° освободитС рСсурси.

Цялостният ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π²ΠΈΠ΄ΠΈ Ρ‚ΡƒΠΊ. ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ΡŠΡ‚ всС ΠΎΡ‰Π΅ Π΅ Π² Π΅Ρ‚Π°ΠΏ Π½Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster