@okkkman

Как настроить сервер на работу двух отдельных приложений?

Здравствуйте.

  1. У меня большой front-end на Vue.js (админка там же), собранный с помощью Webpack (Node.js + куча модулей и плагинов) без Vue-CLI
    Есть несколько конфигураций для development и production, т.е. пока Node.js используется только для создания конечного билда (файлы появляются в ./dist)

  2. Так же имеется back-end API на PHP-фреймворке Symfony (+ Redis, RabbitMQ и MySQL)
    В качестве веб-сервера используется Nginx



Две эти части пока никак не связаны, но теперь настал момент это сделать и возникло множество вопросов, т.к. ранее не приходилось писать комплексные SPA-приложения еще и упаковывать в Docker

Вопросы:

1. Как грамотно и, самое главное, безопасно написать два конфига для Nginx?
Первый должен открывать скомплированное Vue приложение, а второй для общения с API

При этом, статичные файлы, загруженные через API (изображения, видео и etc.), которые хранятся в папке /assets/uploads приложения Symfony, должны так же открываться по адресу: www.site.ru/uploads/*

+ в будущем планируется подключение SSR в легкой связке с Express.js, возможно, это тоже надо учитывать при конфигурации сервера

2. Есть какие-то нюансы в докеризации?

В общем, любые советы, примеры и размышления будут очень кстати

Заранее огромное спасибо!
  • Вопрос задан
  • 882 просмотра
Решения вопроса 1
Softovick
@Softovick
программист, администратор
Если используете Докер и прямо хотите докеризировать с мастабированием, то используйте сеть докера для связи между контейнерами для начала.
У вас должно быть 1 контейнер с nginx наружу (80 порт и/или 443), 1 контейнер для сборки приложения VueJS, 1 контейнер для работы с PHP-проектом и дальше что там у вас, по контейнеру для СУБД (1 Redis, 1 RabbitMQ, 1 MySQL). Каждому контейнеру дайте нормальное уникальное имя, чтобы можно было их подключать друг к другу по dns-имени. Наружу порт только для nginx давайте, он будет за все отвечать.
1. Контейнер с nginx отдает статику, собранную из приложения VueJS. Собственно все как обычно - собрали dist, из него и отдаете. В идеале собирать в отдельном контейнере c NodeJS, а полученные данные из dist копировать в какой-нибудь volume наверное и подключить его к контейнеру с Nginx. Это можно делать на уровне файлов docker-compose и автоматизировать при сборке проекта. Этот же volume можно подключить и к контейнеру с backend-api, тогда оно сможет работать с файлами, которые загрузили.
2. Из первого контейнера с nginx по upstream отдавать backend-api, который будет обращаться к еще одному контейнеру, где крутится PHP и собственно ваш symphony проект. Наружу этот контейнер не пускайте, подключайте к первому контейнеру через имя. Таким образом вы сможете запустить несколько контейнеров с api, указав все их dns-имена в разделе нужного upstream. Уже получаете горизонтальную масштабируемость, эти контейнеры потом можно запускать вообще на разных серверах, соединив их, например при помощи Docker Swarm или в Kubernetes. Опять же все можно оформить на уровне файлов конфигурации Docker Compose, там не сложно, достаточно почитать документацию.
3. Все контейнеры с СУБД запускайте тоже в отдельных контейнерах, где нужно - создавайте volume для хранения БД. Их тоже наружу не пускайте, биндите на уровне Docker с контейнером (ами) с backend-api. Вообще если предполагается серьезная нагрузка, то СУБД вообще рекомендуют запускать не в контейнерах, но тогда чуть сложнее автоматизировать привязку и масштабирование будет. Для начала можно и в контейнерах, когда она придет, эта нагрузка то... Тем более контенеры с СУБД тоже можно в нескольких экземплярах запускать, между ними репликацию сделать или вообще шардинг. Все это можно наверное во всех описанных БД сделать, но с шардингом помучаться конечно придется. Репликация проще всего. А уже к ним подключаться из backend-api по dns-именам, как настроите.

Как то так.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
мои конфиг nginx, может пригодится. Без докера, бэк на рельсах и фронт vue
map $sent_http_content_type $expires {
  "text/html" epoch;
  "text/html; charset=utf-8" epoch;
  default off;
}

map $cookie_SESSION $logme {
    "" $perhaps;  # If the cookie is missing, we log if $perhaps
    default   0;
}

map $status $loggable {
    ~^[23]  0;
    default 1;
}

split_clients $request_id $perhaps {
    1%        1;  # $perhaps is true 1% of the time
    *         0;
}

server {
  listen 443 ssl http2;
  server_name .medicus72.ru;

  set $rails_api /home/medicus/medicus-api;

  root $rails_api/current/public;

  # listen [::]:443 ssl;

  gzip on;
  gzip_types text/plain application/xml text/css application/javascript;
  gzip_min_length 1000;

  try_files $uri @nuxt;

  location @nuxt {
    proxy_pass http://lombd.ru-central1.internal:4000; # set the adress of the Node.js instance here

    include proxy_params;
    access_log /home/medicus/medicus72.ru/shared/logs/$host.log main;
    access_log /home/medicus/medicus72.ru/shared/logs/sslparams.log sslparams if=$logme;
    expires $expires;
  }

  location ~ ^/(api|rails) {
    proxy_pass http://lombd.ru-central1.internal:4001;

    include proxy_params;
    access_log /home/medicus/medicus-api/shared/log/$host.log main;
  }

  location ~ ^/(assets|packs) {
    expires max;
    gzip_static on;
  }

  location ~ \.php$ { deny all; }

  ssl_certificate /etc/letsencrypt/live/prd.medicus72.ru/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/prd.medicus72.ru/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/prd.medicus72.ru/chain.pem;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  # include /etc/letsencrypt/options-ssl-nginx.conf;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы