Конфигурация Docker для Nest.js приложения в сети Traefik

Данная конфигурация представляет собой полный цикл разработки и развертывания серверного Nest.js приложения, начиная от написания кода и заканчивая его публикацией.

Сервер упакован в Docker контейнер, настроенный на работу с реверс прокси Traefik. Имеется два режима запуска проекта — developer и production.

Конфигурация используется в нашем приложении Messenger.

Ниже приведем код docker-compose.yml (production):

YAML
services:
  messenger-backend:
    container_name: messenger-backend
    build:
      context: .
      target: 'production-stage'
    env_file:
      - /data/secrets/${SERVER_DOMAIN}/messenger-backend/app.env
      - /data/secrets/${SERVER_DOMAIN}/messenger-backend/static.env
    environment:
      PORT: 5000
      NODE_ENV: production

      POSTGRES_HOST: postgres
      POSTGRES_USER: messenger
      POSTGRES_DB: messenger
      POSTGRES_PORT: 5432

      WEB_CLIENT_URL: https://messenger.${SERVER_DOMAIN}
      APP_CLIENT_URL: https://localhost
      API_URL: https://msg.${SERVER_DOMAIN}

      ACCESS_TOKEN_MAX_AGE: 60d
      REFRESH_TOKEN_MAX_AGE: 15m
      COOKIE_REFRESH_TOKEN_MAX_AGE: 6048000000
    volumes:
      - /data/appdata/messenger:/app/static/user
    command: ["node", "dist/main.js"]
    restart: unless-stopped
    networks:
      - proxynet
    labels: 
      - "traefik.enable=true"
      - "traefik.http.routers.msgbe.rule=Host(`msg.${SERVER_DOMAIN}`)"
      - "traefik.http.routers.msgbe.entrypoints=https"
      - "traefik.http.routers.msgbe.service=msgbe-service"
      - "traefik.http.services.msgbe-service.loadbalancer.server.port=5000"
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
networks:
  proxynet:
    external: true
    


Для development так же есть свой docker-compose.dev.yml:

YAML
services:
  messenger-backend-dev:
    container_name: messenger-backend-dev
    build:
      context: .
      target: 'develop-stage'
    env_file:
      - /data/secrets/${SERVER_DOMAIN}/messenger-backend/app.env
      - /data/secrets/${SERVER_DOMAIN}/messenger-backend/static.env
    environment:
      PORT: 5000
      NODE_ENV: development

      POSTGRES_HOST: postgres
      POSTGRES_USER: messenger
      POSTGRES_DB: messenger
      POSTGRES_PORT: 5432

      WEB_CLIENT_URL: https://messenger.${SERVER_DOMAIN}
      APP_CLIENT_URL: https://localhost
      API_URL: https://msg.${SERVER_DOMAIN}

      ACCESS_TOKEN_MAX_AGE: 365d
      REFRESH_TOKEN_MAX_AGE: 365d
      COOKIE_REFRESH_TOKEN_MAX_AGE: 6048000000
    volumes:
      - .:/app:rw
      - /data/appdata/messenger:/app/static/user
    command: sh -c "npm install && npm run start:dev"
    restart: unless-stopped
    networks:
      - proxynet
    labels: 
      - "traefik.enable=true"
      - "traefik.http.routers.msgbe.rule=Host(`msg.${SERVER_DOMAIN}`)"
      - "traefik.http.routers.msgbe.entrypoints=https"
      - "traefik.http.routers.msgbe.service=msgbe-service"
      - "traefik.http.services.msgbe-service.loadbalancer.server.port=5000"
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
networks:
  proxynet:
    external: true
    


Его содержимое похоже на конфигурацию production, но есть несколько важных отличий:

  • target: 'develop-stage'
  • В volumes добавляется еще .:/app:rw, что позволяет в процессе разработки динамически обновлять файлы проекта в контейнере
  • command: sh -c "npm install && npm run start:dev" — здесь, npm install необходимо указать для того, что бы дирекотория node_modules была доступна для отслеживания зависимостей в VS Code.

Dockerfile

Эта конфигурация Dockerfile описывает многоэтапную сборку образа для Node.js приложения:

Dockerfile
# develop stage
FROM node:22.8.0-alpine3.20 AS develop-stage
WORKDIR /app
COPY package*.json ./
RUN npm config set fund false --location=global
COPY . .


# build stage
FROM develop-stage AS build-stage
RUN npm install
RUN npm run build


# production stage
FROM node:22.8.0-alpine3.20 AS production-stage
WORKDIR /app
COPY --from=build-stage /app/node_modules /app/node_modules
COPY --from=build-stage /app/dist /app/dist
COPY --from=build-stage /app/static /app/static
COPY package.json ./
CMD ["node", "dist/main.js"]
EXPOSE 5000


Он состоит из трёх основных этапов:

  1. Разработка (develop stage):
  • Базируется на Alpine-образе Node.js для его легковесности и эффективности.
  • Устанавливает рабочую директорию /app.
  • Копирует файлы package.json и package-lock.json (package*.json для большей гибкости).
  • Отключает спам в консоли о финансировании (fund) пакетов в NPM.
  • Копирует все остальные файлы приложения в контейнер.
  1. Сборка (build stage):
  • Использует промежуточный образ develop-stage как основу.
  • Устанавливает зависимости с помощью npm install.
  • Запускает процесс сборки приложения с помощью npm run build, формируя конечную сборку в директории dist.
  1. Продакшн (production stage):
  • Начинается с чистого Node.js Alpine-образа той же версии.
  • Устанавливает рабочую директорию /app.
  • Копирует директорию node_modules из build-stage для использования в продакшене.
  • Копирует директории dist и static из build-stage, содержащие скомпилированные и статические файлы приложения.
  • Копирует package.json.
  • Определяет, что при запуске контейнера должен исполняться файл dist/main.js через Node.js.
  • Открывает 5000 порт (в дальнейшем он будет перенаправлен через реверс-прокси Traefik, который позволит управлять SSL сертификатами для обеспечения соединения HTTPS).


Если вам интересен наш проект, есть вопросы, замечания, или предложения — оставляйте комментарии или пишите на почту: checkerwars@mail.ru

Кроме того, автор проекта ищет работу. Мое резюме.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *