У меня есть два образа докеров, один из которых — это мой nginx, обслуживающий файлы, созданные моим реагирующим приложением, другой — внутренний экспресс-сервер, оба работают на одном компьютере. Проблема, с которой я сталкиваюсь сейчас, заключается в том, что мое внешнее приложение использует реагирующий маршрутизатор для создания внешних маршрутов в виде комнат. В первый раз, когда я получаю доступ к маршруту через API реакции-маршрутизатора useHistory
, он работает, как и ожидалось. Но после обновления я получаю 404 не найдено от nginx.
Это мой файл nginx.conf. Насколько я понимаю, когда приходит запрос, nginx ищет самый длинный совпадающий путь, в моем случае маршрут что-то вроде HqHvNw
. Итак, nginx находит location /
в качестве подходящего маршрута. И поскольку он не находит каталог HqHvNw
, он отступает и обслуживает файл index.html' in
/usr/share/nginx/html`. Но в настоящее время он работает не так, как я ожидал, он возвращает 404 не найдено.
http {
server {
listen 80;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
}
}
}
}
Журналы, которые я получаю, таковы, почему он не обслуживает файл index.html
?
2023/04/02 19:50:35 [error] 9#9: *1 open() "/usr/share/nginx/html/HqHvNw" failed (2: No such file or directory), client: xx.xxx.xx.xx, server: , request: "GET /HqHvNw HTTP/1.1", host: "yy.yy.y.yy"
Что я пробовал:
docker exec
в контейнер, чтобы убедиться, что нужные файлы находятся в каталоге.chmod -R 777
весь html-каталог, чтобы убедиться, что у него нет проблем с разрешениями.Пожалуйста, поправьте меня, если я что-то неправильно понял, любые советы также будут оценены! Спасибо!
Обновлено: вот мой интерфейсный файл докеров
FROM node:alpine as builder
WORKDIR /client
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm install --force
RUN npm run build
FROM nginx:alpine
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf
## Remove default nginx index page
RUN rm -rf /usr/share/nginx/html/*
# Copy from the stage 1
COPY --from=builder /client/build /usr/share/nginx/html
RUN ls -la /usr/share/nginx/html
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Хм, так что я могу сделать, чтобы исправить это?
Не имею представления. Я использую строки запроса для своих маршрутов, чтобы избежать таких проблем. Или используйте теги привязки, если у вас не будет рендеринга на стороне сервера.
Я думаю, вам нужно изменить его на try_files $uri /index.html;
с try_files $uri $uri /index.html
Я тоже не эксперт в создании этих конфигурационных файлов, но я посмотрел на свой старый проект, который работает, и вот что у меня есть :-)
Вы скопировали файл index.html в образ докера с помощью соответствующей команды в Dockerfile? или вы монтируете том с index.html?
Да, я использую COPY --from=builder /client/build /usr/share/nginx/html
. Я добавил свой файл докеров в исходный пост.
@LarsVonk Я пробовал ваш подход, но все равно получаю ту же ошибку. :<
Обычно вам не нужно (или не нужно) $uri/
(см. этот ответ). Вы уверены, что конфигурация nginx в вашем вопросе совпадает с содержимым .nginx/nginx.conf
? К вашему сведению, добавление поддержки CORS для вашего внешнего приложения не имеет смысла.
Я не рекомендую перезаписывать основной файл конфигурации nginx, если вы не собираетесь делать это должным образом (у вас отсутствуют несколько важных директив, таких как events
).
Вместо этого укажите конфигурацию сайта по умолчанию в /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html; # 👈 this is all I added to the existing file
}
# etc...
}
Ваш Dockerfile также может быть более оптимизирован за счет более эффективного использования кеша слоев.
FROM node:alpine as builder
WORKDIR /client
# Copy build files first
COPY package.json .
COPY package-lock.json .
# Install dependencies
RUN npm ci
# Copy source code
COPY . .
# Build
RUN npm run build
FROM nginx:alpine
COPY ./.nginx/nginx.conf /etc/nginx/conf.d/default.conf
# Copy from the stage 1
COPY --from=builder /client/build /usr/share/nginx/html
Наконец, не забудьте установить файл .dockerignore
, чтобы избежать копирования ненужных файлов.
.git/
build/
node_modules/
Dockerfile
Спасибо! Я переключился на использование default.conf, и он отлично работает!
Я верю, что он будет ДОПОЛНЯТЬСЯ
/index.html
, а не удалять последний и создавать резервную копию.