Наш проект разрастается, что приводит к необходимости добавлять дополнительные службы, по сути отвечающие за один элемент логи��и.  

Для тех кто пропустил, начало

Поскольку мы изначально начали создавать приложение путем разделения компонентов на небольшие сервисы, которые можно развертывать и использовать независимо друг от друга давайте рассмотрим из чего в дальнейшем будет состоять наше приложение. А состоять оно будет из следующих сервисов:

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 и запустим наш контейнер.