В этой статье будет показано, как с помощью генератора Create React App поместить в контейнер React-приложение.
Мы заострим внимание на:
1. Настройке среды разработчика с помощью обновления данных на странице без её перезагрузки;
2. Настройке образа, готового к использованию клиентом, с использованием многокаскадных конструкций.
Создание проекта
Установите Create React App во всех средах:
$ npm install -g create-react-app@3.4.1
Создайте новое приложение:
$ npm init react-app sample --use-npm
$ cd sample
Docker
Добавьте файл Dockerfile в корень проекта
# Возьмите базовый образ
FROM node:13.12.0-alpine
# задайте рабочую директорию
WORKDIR /app
# добавьте `/app/node_modules/.bin` в $PATH
ENV PATH /app/node_modules/.bin:$PATH
# установите зависимости приложения
COPY package.json ./
COPY package-lock.json ./
RUN npm install --silent
RUN npm install react-scripts@3.4.1 -g --silent
# добавьте приложение
COPY . ./
# запустите приложение
CMD ["npm", "start"]
Вы можете заглушить NPM выход с помощью команды --silent. Зачастую это не одобряется другими разработчиками, хоть и может
уменьшить количество ошибок. Помните это, чтобы не тратить время на поиск и устранение ошибок
Добавьте файл .dockerignore:
node_modules
build
.dockerignore
Dockerfile
Dockerfile.prod
Это ускорит процесс построения в Docker, так как ваши локальные зависимости внутри директории “node_modules” не будут отправлены в Docker Daemon.
Создайте и назовите образ Docker:
$ docker build -t sample:dev .
Затем после построения запустите контейнер:
$ docker run \
-it \
--rm \
-v ${PWD}:/app \
-v /app/node_modules \
-p 3001:3000 \
-e CHOKIDAR_USEPOLLING=true \
sample:dev
Если вы столкнулись с ошибкой "ENOENT: no such file or directory, open '/app/package.json"., возможно, вам требуется подключить дополнительный том -v /app/package.json.
Что здесь происходит?
1. Команда запуска докера создаёт и отправляет запрос на новый контейнер из образа, который мы только что создали.
2. -it запускает контейнер в интерактивном режиме. Почему это необходимо? Из-за того, что в версии 3.4.1 react-scripts, являющийся причиной создания контейнера, появляется сразу после запуска (если не обозначен специальный CI режим). Таким образом, интерактивный режим является для нас необходимостью.
3. –rm удаляет контейнер и тома после появления контейнера.
4. -v ${PWD}:/app помещает код в контейнер как “/app”. {PWD} может не работать с Windows. Посмотрите эти вопросы на Stack Overflow для получения дополнительной информации.
5. Так как, фактически, мы хотим использовать папку “node_modules” в виде контейнера, мы настроили ещё один том: -v /app/node_modules. Теперь у вас должна появиться возможность удалить локальные настройки “node_modules”.
6. -p 3001:3000 открывает порт 3000 для других Docker-контейнеров в той же сети (для межконтейнерной коммуникации) и порт 3001 для хоста. Для получения бо́льшей информации обратитесь к этим вопросам на Stack Overflow.
7. Наконец, -e CHOKIDAR_USEPOLLING=true запускает механизм опроса через chokidar (который объединяет fs.watch, fs.watchFile и fsevents), таким образом начинает работать горячая перезагрузка.
Откройте ваш браузер и введите http://localhost:3001/, после этого вы должны увидеть приложение. Попробуйте внести изменения в App компонент в редакторе кода. Вы должны увидеть обновление данных без перезагрузки страницы.. Остановите сервер в случае её выполнения.
Что произойдёт, если вы добавите d к ‘-it’?
$ docker run \
-itd \
--rm \
-v ${PWD}:/app \
-v /app/node_modules \
-p 3001:3000 \
-e CHOKIDAR_USEPOLLING=true \
sample:dev
Повторите это у себя для проверки понимания.
Хотите использовать Docker Compose? Добавьте файл docker-compose.yml в корень вашего проекта:
version: '3.7'
services:
sample:
container_name: sample
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/app'
- '/app/node_modules'
ports:
- 3001:3000
environment:
- CHOKIDAR_USEPOLLING=true Обратите внимание на тома. Без анонимного тома ('/app/node_modules'), директория node_modules будет переписана за счёт создания директории хоста во время выполнения программы. Другими словами, произойдёт следующее:
· Build – в образе создаётся директория node_modules.
· Run – в контейнере задаётся текущая директория, переписывая node_modules, установленное в процессе Build.
Создайте образ и уничтожьте контейнер:
$ docker-compose up -d --build
Убедитесь, что приложение запущено в браузере и снова проверьте горячую перезагрузку. Прежде чем продолжить, уничтожьте контейнер:
$ docker-compose stop
Для пользователей Windows: Появились проблемы с корректной работой томов? Ознакомьтесь со следующими ресурсами: 1. Docker в установленных Window директориях хоста (Docker on Windows–Mounting Host Directories); 2. Настройка Docker на сетевых устройствах Windows (Configuring Docker for Windows Shared Drives).
Также вам может понадобится добавить COMPOSE_CONVERT_WINDOWS_PATHS=1 в блок настройки файла Docker Compose. Ознакомьтесь с инструкцией по объявлению стандартных переменных среды в файле для получения дополнительной информации
Продакшен
Давайте создадим отдельный файл Docker Dockerfile.prod, используемый в продакшене:
# создаём среду
FROM node:13.12.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci --silent
RUN npm install react-scripts@3.4.1 -g --silent
COPY . ./
RUN npm run build
# боевая среда
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Здесь мы получаем преимущество многоступенчатой сборки для создания вре́менного образа, с помощью которого строится артефакт –статичный React-файл – именно он копируется на образ, идущий в продакшен. Вре́менный образ избавляется от файлов-первоисточников и папок, ассоциированных с образом. В итоге мы получаем только основную часть проекта – готовый к продакшену образ.
Чтобы узнать больше о многоступенчатых сборках, посмотрите запись в блоге со сравнением обычного и многоступенчатого шаблона разработки в Docker.
Используя боевой Docker-файл, создаём и называем образ:
$ docker build -f Dockerfile.prod -t sample:prod .
Запускаем контейнер:
$ docker run -it --rm -p 1337:80 sample:prod Отправляемся в http://localhost:1337/ в вашем браузере, чтобы увидеть приложение.
Проверяем приложение с помощью нового файла Docker Compose, который так и называется docker-compose.prod.yml:
version: '3.7'
services:
sample-prod:
container_name: sample-prod
build:
context: .
dockerfile: Dockerfile.prod
ports:
- '1337:80'
Уничтожаем контейнер:
$ docker-compose -f docker-compose.prod.yml up -d --build
Проверяем это ещё раз в браузере.
React Router и Nginx
Если вы пользуетесь React Router, тогда вам понадобится изменить стандартные настройки Nginx на время создания контейнеров:
COPY --from=build /app/build /usr/share/nginx/html
Вносим изменения в Dockerfile.prod:
# создаём среду
FROM node:13.12.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci --silent
RUN npm install react-scripts@3.4.1 -g --silent
COPY . ./
RUN npm run build
# боевая среда
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
# новое
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Создаём папку, включающую файл nginx.conf:
└── nginx
└── nginx.conf
Nginx.conf:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Следующие шаги:
С помощью этой статьи вы должны научиться добавлять React одновременно в среды разработки и продакшена в большие проекты, созданные с помощью Docker.
Дискуссия
Написал Rocky 9
Опубликовано в: Установка nginx c PHP-FPM под CentOS 7.0 in LinuxНаписал Константин
Опубликовано в: Докеризация стека LEMP под Ubuntu c помощью Compose in LinuxНаписал bammbr
Опубликовано в: Шлюз для маленького отдела на Red Hat 9 in LinuxНаписал Федор
Опубликовано в: Установка и конфигурация Samba на CentOS 7 in LinuxНаписал Evgenytrl
Опубликовано в: Загрузка файлов с помощью Wget in Linux