我是一名全栈开发人员,我需要使用 Docker 部署我的第一个应用程序。 我的堆栈是用于后端的 php/Symfony、用于前端的 React/NextJS 和用于数据库的 MariaDB。我想使用 nginx 作为服务器。
首先,我的前端似乎正在使用此配置,因为重定向是正确的,我可以通过 http://my-app.com 访问我的网站 但是,当我想通过前端向后端发出请求时,我在 Firefox 中收到 CORS 错误(CORS 同源策略,没有错误代码)。当我想像在开发中那样通过 http://my-app.com:9000 访问我的后端时,我收到错误:该网站不可用,等等。
所以我在这里迷路了。我想我的配置中可能有错误,但我似乎无法确定错误在哪里,而且我已经被困在这个问题上好几天了......
这是我的 docker-compose.yml:
services:
frontend:
build:
context: ./my-app-front
dockerfile: Dockerfile
container_name: my-app-front
ports:
- "3000:3000"
networks:
- bridge
backend:
build:
context: ./my-app-back
dockerfile: Dockerfile
container_name: my-app-back
volumes:
- backups:/var/backups/my-app
ports:
- "9000:9000"
networks:
- bridge
depends_on:
- db
environment:
DATABASE_URL: mysql://root:password@db:3306/db_name?serverVersion=mariadb-10.5.8
nginx:
image: nginx:stable-alpine
container_name: my-app-nginx
environment:
DATABASE_URL: mysql://root:password@db:3306/db_name?serverVersion=mariadb-10.5.8
ports:
- "80:80"
volumes:
- ./my-app/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- frontend
- backend
- db
networks:
- bridge
db:
image: mariadb:10.5.8
container_name: my-app-db
environment:
MYSQL_USER: root
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: db_name
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- bridge
networks:
bridge:
driver: bridge
volumes:
db_data:
backups:
这是我的 nginx 配置:
server {
listen 80;
server_name my-app.com;
add_header 'Access-Control-Allow-Origin' 'http://my-app.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With, Accept' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
location / {
proxy_pass http://my-app.com:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
location /assets/ {
root /var/www/src/public;
try_files $uri $uri/ =404;
}
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
就是这样,伙计们!
如果我可以提供更多信息,我很乐意!
我尝试了多种配置变体,直到这一个,我认为问题在于卷和其中的路径......
我的设置与你的几乎相同。这是我的 Compose 文件的样子。我已经删除了一些特定于设置的配置,但这里仍然可能有一些您不需要的额外内容。请随意忽略这些或根据需要进行调整:
services:
nginx:
image: nginx:1.25.3-alpine
restart: unless-stopped
environment:
FPM_HOST: ${COMPOSE_PROJECT_NAME}_api
NEXT_HOST: ${COMPOSE_PROJECT_NAME}_node
NGINX_SERVER_NAME: ${NGINX_SERVER_NAME}
NGINX_ROOT: ${NGINX_ROOT}
volumes:
- ./api:/var/www/html
- ./logs:/var/log/nginx
- ./docker/nginx:/etc/nginx/templates
depends_on:
- api
- frontend
networks:
default:
aliases:
- ${COMPOSE_PROJECT_NAME}_nginx
- ${NGINX_SERVER_NAME}
api:
build:
context: ../api
args:
PHP_VERSION: ${PHP_VERSION:-8.3}
environment:
XDEBUG_CONFIG: "client_host=host.docker.internal start_with_request=1"
XDEBUG_MODE: "develop,debug,profile"
restart: unless-stopped
ports:
- "9000"
develop:
watch:
- action: rebuild
path: api/composer.lock
- action: sync
path: api/config
target: /var/www/html/config
- action: sync
path: api/src
target: /var/www/html/src
volumes:
- storage:/var/www/html/var/storage
networks:
default:
aliases:
- ${COMPOSE_PROJECT_NAME}_api
frontend:
build:
context: ../frontend
restart: unless-stopped
ports:
- ${DEV_PORT:-3000}:3000
entrypoint:
- npm
command:
- run
- dev
develop:
watch:
- action: rebuild
path: frontend/package-lock.json
- action: rebuild
path: frontend/next.config.mjs
- action: sync
path: frontend/resources
target: /var/www/html/resources
- action: sync
path: frontend/src
target: /var/www/html/src
networks:
default:
aliases:
- ${COMPOSE_PROJECT_NAME}_node
db:
image: mariadb:11.2.2
restart: unless-stopped
ports:
- "${DB_PORT:-}:3306"
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASS}
MYSQL_DATABASE: ${DB_NAME}
volumes:
- mysql:/var/lib/mysql
networks:
default:
aliases:
- ${COMPOSE_PROJECT_NAME}_${MYSQL_HOST:-mysql}
volumes:
mysql:
storage:
这是我的 NGINX 配置:
upstream frontend {
server ${NEXT_HOST}:3000;
}
server {
listen 80 default_server;
server_name ${NGINX_SERVER_NAME};
root ${NGINX_ROOT};
index index.php;
client_max_body_size 128M;
location / {
proxy_buffers 16 16k;
proxy_buffer_size 32k;
proxy_pass http://frontend;
}
location /api {
alias ${NGINX_ROOT}/public/;
add_header X-Forwarded-Prefix "/api";
try_files $uri /index.php?$args;
}
location /_next/webpack-hmr {
proxy_pass http://frontend/_next/webpack-hmr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_intercept_errors on;
fastcgi_pass ${FPM_HOST}:9000;
fastcgi_param SCRIPT_FILENAME $document_root/public/$fastcgi_script_name;
fastcgi_param SERVER_PORT "443";
fastcgi_param HTTPS "on";
}
}
这是我的 API .env 文件。请注意,所有其他设置都是通过我的 Docker Compose 文件和外部项目 .env 文件中的环境变量设置的:
###> symfony/framework-bundle ###
APP_ENV=prod
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
DB_NAME=share
DB_USER=gh
DB_PASS=<secret>
DB_PORT=3306
DB_HOST=gh-file-share_mysql
###< doctrine/doctrine-bundle ###
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
###< nelmio/cors-bundle ###
它的工作原理:
我使用
nelmio/cors-bundle
包来管理 API 方面的 CORS,并通过 NGINX 将所有以 /api
开头的请求路由到 FPM。这样做有一个缺点,因为 NextJS 目前使用 /api
前缀来实现其某些功能。就我而言,我根本不使用该功能,但如果您使用,那么 YMMV。
我目前正在使用 Traefik 来管理我的本地 URL(我已省略标签),因此我可以通过
https://my-project.docker.localhost
访问我的项目前端,并且所有 API 调用都对 https://my-project.docker.localhost/api/v1/{endpoint}
进行。
希望这应该有助于揭开您在当前本地设置中遇到的一些问题。