无法使用 Docker 设置应用程序:php 后端、React 用于前端、nginx 用于服务器、MariaDB 用于数据库

问题描述 投票:0回答:1

我是一名全栈开发人员,我需要使用 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;
    }
}

就是这样,伙计们!

如果我可以提供更多信息,我很乐意!

我尝试了多种配置变体,直到这一个,我认为问题在于卷和其中的路径......

php reactjs docker symfony nginx
1个回答
0
投票

我的设置与你的几乎相同。这是我的 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}
进行。

希望这应该有助于揭开您在当前本地设置中遇到的一些问题。

© www.soinside.com 2019 - 2024. All rights reserved.