Работа с React-приложениями в Docker

Docker – инструмент создания контейнеров, используемый для ускорения разработки и запуска процессов. Если вы работаете с микросервисами, Docker значительно упростит объединение малых независимых сервисов. Он также помогает в устранении особых контекстных ошибок, так как вы можете воспроизвести среду, в которой будет работать продукт, на своём компьютере.

В этой статье будет показано, как с помощью генератора 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.

Авторизуйтесь, чтобы получить возможность оставлять комментарии
Go to top