Как обслуживать приложения React с помощью NGINX и Docker
Существует так много способов, которыми мы можем создавать приложения React и отправлять их в производство. Одним из способов является сборка React с NodeJS или Java, а другой способ - сборка приложения React и подача этого статического контента на веб-сервер NGINX. Когда мы строим с NGINX и докером, нам не нужно иметь дело с временем выполнения сервера или кодом, связанным с сервером. NGINX все, что нам нужно, чтобы собрать приложение для prod и обслуживать сгенерированный статический контент на сервере.
В этом посте мы увидим подробности и реализацию второго подхода. Мы пройдем шаг за шагом с примером.
Вступление
В этом проекте мы собираемся использовать React в качестве библиотеки JS, NGINX в качестве веб-сервера, докер в качестве среды выполнения контейнера.
Если мы посмотрим на диаграмму выше, React создаст приложение и поместит статические ресурсы в папку /build
. Мы размещаем эти ресурсы в расположении по умолчанию NGINX /usr/share/nginx/html
, откуда он обслуживает веб-контент.
Предпосылки
Есть некоторые предпосылки для выполнения этой задачи. Мы должны запустить NGINX в докере, поместить статические ресурсы в NGINX и запустить всю настройку внутри докера. Нам нужно установить nodejs для установки зависимостей. Пожалуйста, установите все перечисленные ниже инструменты, чтобы следовать этому руководству, или вы хотите запустить его на своем компьютере.
Пример проекта
Это простой проект, который демонстрирует обслуживание статического приложения React с NGINX и Docker. У нас есть простое приложение с заголовком, нижним колонтитулом и с сообщением.
Вот пример проекта, где вы можете клонировать и запустить на своей машине
// clone the project
git clone https://github.com/bbachi/react-nginx-docker
// install and start the dependencies
npm install
npm start
// build the docker image
docker build -t react-ui .
// run the app
docker run -d --name reactui -p 80:80 react-ui
Это простое приложение React с заголовком, нижним колонтитулом и сообщениями на панели инструментов. Вот файлы Header.js, Footer.js и App.js
import React from 'react';
const Header = () => {
return (
Simple React App
)
};
export default Header
import React from 'react';
const Footer = () => {
return (
)
};
export default Footer
import React from 'react';
import Header from './header/header'
import Footer from './footer/footer'
import './App.css';
function App() {
return (
Simple React App served by NGINX and Docker
);
}
export default App;
Настроим NGINX
Мы здесь не прорабатываем все, что касается NGINX, и нам достаточно просто пройти через этот проект. Если вы уже знакомы с этим, вы можете перейти к следующему разделу.
Процессы NGINX делятся на один основной процесс и несколько рабочих процессов. Главный процесс заботится об оценке конфигурации и поддержке рабочих процессов, а рабочие процессы заботятся о реальных запросах. Мы можем определить количество рабочих процессов в файле конфигурации, который можно поместить в каталог /usr/local/etc/nginx
, /etc/nginx
или /usr/local/nginx/conf
.
Файл конфигурации состоит из директив, которые формируют модули или контексты. Существует два вида директив: простые директивы и блочные директивы. Простая директива имеет имена и параметры, разделенные пробелом, и заканчивается точкой с запятой, подобной этой listen 80;
. Директива блока такая же, но содержит дополнительную информацию и заключена в фигурные скобки, подобные этой { listen 80; root /usr/share/nginx/html; }
.
Давайте разберемся с конфигурационным файлом NGINX, который мы использовали в этом проекте. Ниже приведен файл nginx.conf, который находится в папке .nginx в корневом каталоге проекта.
Все это контекст в файле конфигурации. У нас есть иерархический контекст, который начинается с основного контекста. Например, worker_processes и события определены в основном контексте, а другой контекст начинается с http. У нас есть другой контекст внутри http, называемый сервером, который прослушивает порт 80 и обслуживает статические ресурсы из корневого каталога /usr/share/nginx/html
.
У нас может быть несколько объявлений сервера в контексте http, и мы можем иметь несколько объявлений местоположения в контексте сервера.
worker_processes 4;
events { worker_connections 1024; }
http {
server {
listen 80;
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
location /appui {
try_files $uri /index.html;
}
}
}
Реализация
Мы используем Docker в качестве среды выполнения контейнера для этого проекта. Мы используем многоэтапные сборки для создания образа Docker. Вот Dockerfile для проекта.
# stage1 as builder
FROM node:10-alpine as builder
# copy the package.json to install dependencies
COPY package.json package-lock.json ./
# Install the dependencies and make the folder
RUN npm install && mkdir /react-ui && mv ./node_modules ./react-ui
WORKDIR /react-ui
COPY . .
# Build the project and copy the files
RUN npm run build
FROM nginx:alpine
#!/bin/sh
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf
## Remove default nginx index page
RUN rm -rf /usr/share/nginx/html/*
# Copy from the stahg 1
COPY --from=builder /react-ui/build /usr/share/nginx/html
EXPOSE 3000 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Этап 1
Мы используем node:10-alpine
как базовый образ для stage1 и копируем package.json
для установки всех зависимостей. Затем мы копируем оставшийся проект позже, таким образом, мы можем пропустить установочные зависимости каждый раз, когда происходит изменение в файлах. Docker использует кэш для построения изображения из существующих слоев, если нет изменений.
Мы строим проект с помощью react-scripts, и все встроенные статические файлы помещаются в папку /build
.
2 этап
Этап 2 начинается с базового образа nginx:alpine
и копирует файл nginx.conf, удаляет индексный файл из корневого расположения и, наконец, копирует все файлы из этапа 1 в корневое расположение, откуда он может обслуживать содержимое.
Билд контейнера и запуск проекта
Давайте создадим проект с помощью этой команды docker build -t react-ui .
и вы можете запустить проект с помощью этой команды docker run -d --name reactui -p 80:80 react-ui
. Вы можете запустить приложение на http://localhost:80
Важные вещи, на которые стоит обратить внимание
Контейнерный порт и порт прослушивания nginx должны быть одинаковыми, равным 80, иначе вы получите ERR_EMPTY_RESPONSE при запуске проекта.
// container port
docker run -d --name react-ui -p 80:80 reactui
// nginx conf
http {
server {
listen 80;
}
}
Мы должны включить эту директиву в файл nginx.conf, иначе все стили отображаются в браузере как простой текст.
include /etc/nginx/mime.types;
Exec Into запуск контейнера
Пока контейнер находится в рабочем состоянии, мы можем выполнить его и посмотреть содержимое файловой системы.
docker exec -it reactui /bin/sh
Мы действительно можем увидеть все содержимое под /usr/share/nginx/html
Резюме
- NGINX может использоваться в качестве веб-сервера или обратного прокси-сервера для обслуживания статического содержимого.
- Все настройки NGINX могут быть размещены в этом файле
nginx.conf
. - Нам нужно создать React приложение и поместить все статические файлы в корневую папку NGINX для работы в Интернете.
- Docker используется в качестве среды выполнения контейнера.
- Мы используем многоэтапные сборки, чтобы уменьшить окончательный размер контейнера и удалить ненужные файлы из производственной среды.
- Образ Docker может быть построен с
docker build -t react-ui .
- Запустите контейнер с этой командой
docker run -d --name reactui -p 80:80 react-ui
- Очень важно сопоставлять порты при запуске контейнера и порта прослушивания в файле nginx.conf. В противном случае вы получите ошибку ERR_EMPTY_RESPONSE .
- Вы можете выполнить exec в контейнер, чтобы исследовать файловую систему с этой командой
docker exec -it reactui /bin/sh