Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Наш проект разрастается, что приводит к необходимости добавлять дополнительные службы, по сути отвечающие за один элемент логики.
Для тех кто пропустил, начало.
Поскольку мы изначально начали создавать приложение путем разделения компонентов на небольшие сервисы, которые можно развертывать и использовать независимо друг от друга давайте рассмотрим из чего в дальнейшем будет состоять наше приложение. А состоять оно будет из следующих сервисов:
1. Сервис Фронтенд Angular
2. Сервис API Nodejs
3. Сервис API Авторизации Node
4. API БД MongoDb
5. API Авторизации MongoDb
6. Сервис Nginx Proxy - основной сервис маршрутизатор
Для создания описанной выше структуры давайте внесем необходимые изменения, создадим каталоги: api, angular, nginx, auth. Перенесем файлы проекта в каталог angular.
Наши отдельные сервисы чрезвычайно просты и могут развертываться независимо друг от друга, а это значит, что для большей простоты и получения модели распределенной инфраструктуры необходимо упаковать службы в контейнер, что предоставит нам дополнительное удобство в развертывании и разработке нашего приложения, для этого мы будем использовать Docker, который позволяет запускать практически любое приложение, безопасно изолированное в контейнере. Безопасная изоляция позволяет запускать на одном хосте много контейнеров одновременно. Docker, состоит из образов, реестров и контейнеров.
Для создания контейнеров используются Образы которые в свою очередь хранятся в реестрах. Есть публичные и приватные реестры, из которых можно скачать либо загрузить образы. Каждый контейнер создается из образа и в нем содержится все, что нужно для работы приложения. Контейнеры могут быть созданы, запущены, остановлены, перенесены или удалены. Каждый контейнер изолирован и является безопасной платформой для приложения.
Подразумевается, что у вас уже установлен Docker.
В нашем приложении мы будем использовать несколько образов, поэтому приступим. Для создания нашего апи переходим в каталог api и создаем Docker файл.
Содержимое Docker файла в каталоге api
FROM node:14.15.0-alpine as development
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install glob rimraf
RUN npm install --only=development
COPY . .
RUN npm run build
FROM node:14.15.0-alpine as production
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . .
COPY --from=development /usr/src/app/dist ./dist
CMD ["node", "dist/main"]
Далее переходим в каталог angular и создаем там два файла, таким образом в дальнейшем мы рассмотрим несколько подходов разделения на prod и dev версии.
Содержимое файла Dockerfile.dev в каталоге angular
FROM node:14.15.0-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 4300
CMD npm run start
Содержимое Dockerfile.prod в каталоге angular
FROM node:13.12.0-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
RUN npm install -g serve
Добавляем в package.json строку необходимую для прослушивания всех интерфейсов из контейнера
"start": "ng serve --host 0.0.0.0 --poll 500",
Причина, по которой это важно, заключается в том, что без него процесс angular прослушивает только локальный интерфейс внутри контейнера, поэтому даже с сопоставлением портов докера соединения извне контейнера не принимаются.
Но если мы добавим параметр, --host 0.0.0.0 то процесс angular будет прослушивать все интерфейсы, а сопоставление портов докера позволит подключаться к нему из-за пределов контейнера.
После этого переходим в корень нашего проекта и создаем docker-compose.yml
Содержимое файла docker-compose.yml
version: '3.4'
services:
angular:
container_name: art-pixel-angular_api_dev
build:
context: ./angular
dockerfile: Dockerfile.dev
command: npm run start
volumes:
- ./angular/src:/usr/src/app/src
- /usr/node_modules
ports:
- 4300:4300
networks:
- art-pixel-network
restart: unless-stopped
api-dev:
container_name: art-pixel_api_dev
image: art-pixel-api-dev:1.0.0
build:
context: ./api
target: development
dockerfile: Dockerfile
command: npm run start:debug
volumes:
- ./api/src:/usr/src/app/src
- /usr/node_modules
ports:
- 3000:3000
- 9229:9229
environment:
- PORT=3000
- HOST=http://localhost
- MONGO_URL=mongodb://api-db:27017/api
depends_on:
- api-db
networks:
- art-pixel-network
restart: unless-stopped
api-db:
image: mongo:4.4.4
container_name: mongo-api-db
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=admin
ports:
- 27017:27017
volumes:
- ./mongo-data-4.4:/data/db
networks:
- art-pixel-network
restart: always
api-prod:
container_name: art-pixel_api_prod
image: art-pixel-api-prod:1.0.0
build:
context: ./api
target: production
dockerfile: ./Dockerfile
command: npm run start:prod
ports:
- 3000:3000
- 9229:9229
networks:
- art-pixel-network
volumes:
- ./api/src:/usr/src/app
- /usr/src/node_modules
restart: unless-stopped
networks:
art-pixel-network:
На сегодня все, в следующей части мы займемся созданием api на Nest.js и запустим наш контейнер.