#node.js #laravel #docker #nginx #cors
#node.js #ларавель #докер #nginx #корс
Вопрос:
кто-нибудь может помочь мне решить эту проблему?
Я запускаю серверную часть php Laravel с fortify и sanctum для аутентификации. У меня также есть интерфейс React, который выполняет вызовы api для этого бэкенда, оба из которых являются докеризованными. Если я запускаю php-сервер локально, проблем с CORs не возникает. Но как только серверная часть запускается через контейнер docker, возникает следующая проблема: Проблема CORS
Access to XMLHttpRequest at 'http://localhost:8000/api/tickets' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
На вкладке сеть мы видим, что URL-адрес запроса не содержит следующих полей в заголовках ответов: «Управление доступом-Разрешить-Учетные данные», «Управление доступом-Разрешить-Происхождение». Есть ли способ, чтобы два контейнера docker разрешали CORs?
Что я пробовал:
- Настройка контейнера NGINX для работы в качестве обратного прокси-сервера, включая добавление полей в:
location / { resolver 127.0.0.11; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Accept,Content-Type'; set $nextjs nextjs_upstream; proxy_pass http://$nextjs; }
- Добавлены все необходимые поля CORS в мои файлы конфигурации для сервера, т. е. cors.php файл.
lt;?php return [ 'paths' =gt; ['*', 'api/*', 'login', 'logout', 'sanctum/csrf-cookie', 'api/tickets'], 'allowed_methods' =gt; ['*'], 'allowed_origins' =gt; ['http://localhost','*'], 'allowed_origins_patterns' =gt; [], 'allowed_headers' =gt; ['X-Custom-Header', 'Upgrade-Insecure-Requests','*'], 'exposed_headers' =gt; [], 'max_age' =gt; 0, 'supports_credentials' =gt; true, ];
Примечание: Эта попытка, в частности, может иметь смысл, поскольку localhost в «allowed_origins» относится к хосту внутри контейнера, но как бы мы изменили его, чтобы он находился вне контейнера? Будет ли это IP-адрес этого контейнера или что-то в этом роде?
- Добавлены дополнительные установки в файл настройки php:
"amp;amp; a2enmod headers amp;amp; sed -ri -e 's/^([ t]*)(lt;/VirtualHostgt;)/1tHeader set Access-Control-Allow-Origin "*"n12/g' /etc/apache2/sites-available/*.conf"
Интересно, что мои маршруты входа/выхода из системы не сталкиваются с той же ошибкой CORS, которая беспокоит мой маршрут: api/билеты, но это не относится к делу, поскольку похоже, что это скорее проблема с контейнерами docker, пытающимися взаимодействовать.
Note: localhost has no port since NGINX serves the yarn/npm build.
Laravel Dockerfile:
# The base image FROM php:8.0.2 as base # Install system dependencies i.e. Zip , curl: RUN apt-get update amp;amp; apt-get install -y zip unzip # Get extensions for PHP amp; Install Postgres RUN apt-get install -y libpq-dev amp;amp; docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql amp;amp; docker-php-ext-install pdo pdo_pgsql pgsql # Get the latest composer: COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Copy everything to the working directory COPY . /app # Set the current working directory WORKDIR /app # Install dependencies for laravel COPY composer.json ./ RUN composer install # Move the exec file to our workdir and give permissions COPY docker-init.sh /usr/local/bin/ RUN chmod x /usr/local/bin/docker-init.sh # Expose internal port which will be mapped EXPOSE 8000 # Run our server ENTRYPOINT [ "docker-init.sh" ]
Frontend Dockerfile:
FROM node:alpine as build # Set the current working directory WORKDIR /usr/app # Install PM2 globally RUN npm install --global pm2 # Get all dependencies COPY package*.json ./ # Copy everything to the working directory RUN npm install --force --production RUN yarn add --dev typescript @types/react COPY . ./ RUN npm run build # Expose internal port which will be mapped EXPOSE 3000 USER node CMD [ "pm2-runtime", "npm", "--", "start" ]
Файл докера Nginx:
# Prod environment FROM nginx:alpine # Remove any existing config files RUN rm /etc/nginx/conf.d/* # Copy config files COPY ./default.conf /etc/nginx/conf.d/ EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
docker-init.sh
#!/bin/bash # Exit immediately if a pipeline returns a non zero status set -e # Change to our working directory cd /app # php artisan migrate # Serve for all IPv4 addresses: php artisan serve --host=0.0.0.0 --port=8000
Спасибо за помощь, ребята
Комментарии:
1. Вы не можете разрешить учетные данные и
*
источники2. Хорошо, я удалил это из файла nginx conf. Та же ошибка, но не думайте, что проблема здесь в NGINX 🙁
3. К вашему сведению, это также есть в вашем
cors.php
файле. Итак, ваша служба Laravel работает в контейнере, который предоставляет порт 8000? Если вы правильно настроили CORS в этой службе, вам не понадобится обратный прокси-сервер4. Так я бы установил «supports_credentials» в значение false? И да, сервер laravel работает в отдельном файле Dockerfile, называемом через docker-compose. Я отредактировал свой оригинальный пост, чтобы включить его
5. «Так я бы установил «supports_credentials» в значение false?» … Это зависит от того, хотите ли вы поддерживать файлы cookie запросов разных источников или нет. Если да, то сохраните его
true
и не используйте*
в разрешенных источниках
Ответ №1:
Решил эту проблему, пришлось внести изменения в app/Http/kernel.php файл. В основном в строках я должен был сделать » веб » и » api » одинаковыми:
protected $middlewareGroups = [ 'web' =gt; [ AppHttpMiddlewareEncryptCookies::class, IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class, IlluminateSessionMiddlewareStartSession::class, // IlluminateSessionMiddlewareAuthenticateSession::class, IlluminateViewMiddlewareShareErrorsFromSession::class, AppHttpMiddlewareVerifyCsrfToken::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ], 'api' =gt; [ EnsureFrontendRequestsAreStateful::class, 'throttle:api', IlluminateRoutingMiddlewareSubstituteBindings::class, ], ];
Становится:
protected $middlewareGroups = [ 'web' =gt; [ AppHttpMiddlewareEncryptCookies::class, IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class, IlluminateSessionMiddlewareStartSession::class, // IlluminateSessionMiddlewareAuthenticateSession::class, IlluminateViewMiddlewareShareErrorsFromSession::class, AppHttpMiddlewareVerifyCsrfToken::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ], 'api' =gt; [ EnsureFrontendRequestsAreStateful::class, 'throttle:api', IlluminateRoutingMiddlewareSubstituteBindings::class, AppHttpMiddlewareEncryptCookies::class, IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class, IlluminateSessionMiddlewareStartSession::class, IlluminateViewMiddlewareShareErrorsFromSession::class, AppHttpMiddlewareVerifyCsrfToken::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ], ];