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