Вопрос или проблема
Я разрабатываю одностраничное приложение на VueJS и для локальной разработки использую Docker с файлом docker-compose.yml
для управления контейнером Nginx в качестве веб-сервера и контейнером Node для компиляции ресурсов.
На данный момент есть одна страница по маршруту /configurator
, на которую должен перенаправляться корневой маршрут /
, и с роутером Vue это работает отлично: обращение к /
корректно перенаправляется на /configurator
.
Проблема возникает при обновлении страницы, поскольку Nginx не может обработать запрос, так как нет подходящего файла по указанному URI для обслуживания.
Документация VueJS указывает, что для перенаправления каждого запроса на индекс проекта и соответственно для того, чтобы роутер Vue мог обрабатывать навигацию, необходимо настроить секцию location
в конфигурации Nginx следующим образом:
location / {
try_files $uri $uri/ /index.html;
}
Поэтому я создал пользовательский файл nginx.conf
и добавил/переименовал его в контейнере Nginx через мой файл docker-compose.yml
, как указано ниже, но я все равно получаю 404 от Nginx.
Проверяя изнутри контейнера Nginx с помощью nginx -T
, я правильно вижу свой пользовательский файл, но заметил, что файл default.conf
находится последним в списке, поэтому я подумал, что Nginx добавляет дополнительные файлы в алфавитном порядке, и так как мой не последний, моя пользовательская конфигурация была перезаписана конфигурацией из default.conf
. Я отредактировал свой docker-compose.yml
, чтобы добавить его под именем z_custom.conf
, просто чтобы быть уверенным, что он будет последним, но ничего не изменилось.
Искал в интернете и заметил, что каждый пример, который я нашел, имел содержимое пользовательского файла в точности таким же, как у файла по умолчанию, за исключением необходимых изменений, поэтому я подумал, что мне действительно нужно полностью перезаписать файл default.conf
и отредактировать нужную секцию, но не смог найти никаких явных указаний на этот счет.
Правильно ли это или есть способ фактически объединить только мою пользовательскую секцию с всей конфигурацией по умолчанию?
custom.conf
server {
# Конфигурация роутера Vue
location / {
try_files $uri $uri/ /index.html;
}
}
docker-compose.yml
webserver:
image: nginx:latest
container_name: webserver
restart: unless-stopped
ports:
- 80:80
volumes:
- ./application/public:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/custom.conf:ro
Обновление #1: добавление server_name
в файл пользовательской конфигурации
Следуя ответу @tero-kilkanen, я просто попробовал добавить server_name localhost
внутрь корневой секции server
моего конфигурационного файла и обновил docker-compose.yml
, чтобы скопировать его внутрь образа Nginx как localhost.conf
, но ничего не изменилось, по прежнему получаю 404 на неиндексируемых маршрутах.
Обновление #2
Не заметил раньше, что предыдущее обновление создает конфликт между конфигурацией по умолчанию и пользовательской конфигурацией, так как оба файла объявляют одно и то же имя сервера, поэтому теперь я просто заменяю default.conf
своим пользовательским файлом и обновил секцию location
следующим образом, но по-прежнему получаю 404 на некорневых маршрутах.
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
Запуск nginx -T
и nginx -t
подтверждает, что мой пользовательский конфигурационный файл читается и используется правильно:
root@be898ad4ca17:/# nginx -T
nginx: файл конфигурации /etc/nginx/nginx.conf имеет правильный синтаксис
nginx: тест конфигурационного файла /etc/nginx/nginx.conf прошел успешно
# конфигурационный файл /etc/nginx/nginx.conf:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
# конфигурационный файл /etc/nginx/mime.types:
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
# конфигурационный файл /etc/nginx/conf.d/default.conf:
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
# перенаправить страницы ошибок сервера на статическую страницу /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# проксировать PHP-скрипты к Apache, слушающему на 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# передать PHP-скрипты серверу FastCGI, слушающему на 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# запретить доступ к файлам .htaccess, если корневая папка Apache совпадает с корневой папкой nginx
#
#location ~ /\.ht {
# deny all;
#}
}
Лучшей практикой является указание server_name
в вашем блоке server
. Тогда nginx будет использовать этот server
блок для вашего приложения, когда вы запрашиваете страницу, используя имя в URL.
Ответ или решение
Проблема, с которой вы столкнулись, связана с маршрутизацией в одностраничном приложении (SPA) на VueJS с использованием Nginx. Ваша конфигурация Nginx должна обеспечивать правильное перенаправление запросов на index.html
, чтобы Vue Router мог обрабатывать маршруты во время обновления страницы.
Исходя из вашего описания, вы уже сделали несколько шагов, чтобы исправить это. Давайте пройдёмся по ключевым моментам:
1. Корректная конфигурация Nginx
Вам нужно убедиться, что конфигурация сервера Nginx правильно настроена для обработки маршрутов Vue Router. Вот пример полной конфигурации на основе вашего кода:
server {
listen 80;
listen [::]:80;
server_name localhost; # Убедитесь, что это название сервера совпадает с тем, что вы используете в URL
root /usr/share/nginx/html; # Укажите директорию, где хранится ваш index.html
# Основная конфигурация обработки маршрутов
location / {
try_files $uri $uri/ /index.html;
}
# Обработка ошибок
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
2. Обновление docker-compose.yml
В вашем docker-compose.yml
убедитесь, что ваш файл конфигурации Nginx корректно подключен. Вот пример того, как это должно выглядеть:
version: '3'
services:
webserver:
image: nginx:latest
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./application/public:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro # Переименуйте свой файл конфигурации
Обратите внимание, что в этом примере nginx.conf
переименован в default.conf
. Это важно, так как Nginx загружает конфигурацию, находящуюся в файле default.conf
. Если вы хотите использовать другой файл, убедитесь, что другие конфигурации так же не конфликтуют.
3. Проверка конфигурации
После того, как вы внесли изменения в конфигурацию, убедитесь, что Nginx читает вашу конфигурацию правильно. Вы можете выполнить команду внутри контейнера:
nginx -T
Эта команда покажет вам все загруженные конфигурации, и вы должны убедиться, что ваша конфигурация отображается корректно.
4. Тестирование
После внесения всех изменений и перезапуска контейнера Nginx выполните тест, обновив страницу на маршруте /configurator
. Если всё работает корректно, вы должны увидеть результат без ошибок 404.
Заключение
Если у вас по-прежнему возникают проблемы, проверьте также, что у вас нет других конфигурационных файлов, которые могут переопределять ваше поведение (например, другие файлы в /etc/nginx/conf.d/
). Если проблема окажется сложнее, рассмотрите возможность добавления логирования в вашем Nginx, чтобы лучше понимать, что происходит при запросах.
Надеюсь, это поможет вам решить проблему с маршрутизацией в VueJS с использованием Nginx! Если у вас есть дополнительные вопросы, не стесняйтесь их задавать.