You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 7应用Docker Swarm多副本部署登录失败问题排查

问题分析与解决方案

核心原因

你猜的没错,问题出在会话不共享上。Symfony默认用本地文件存储会话,当部署多个backend_app副本时,每个容器都有自己独立的会话文件目录。Nginx默认轮询转发请求到不同副本,登录操作在其中一个容器生成会话后,后续请求可能落到另一个没有该会话的容器,导致登录状态丢失。

另外你的Swarm配置里有个小问题:backend_app的ports字段不需要配置,因为Nginx是通过Swarm服务发现(http://backend_app:80)访问后端,多个副本绑定同一个主机端口8000会引发冲突。

解决方案步骤

1. 配置Symfony使用共享会话存储

推荐用Redis作为共享会话存储,步骤如下:

  • 在PHP镜像中安装Redis扩展(如果你的镜像还没装),可以在Dockerfile里加:
    RUN pecl install redis && docker-php-ext-enable redis
    
  • 修改Symfony的config/packages/framework.yaml,将会话存储改为Redis:
    framework:
        session:
            handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler
            cookie_secure: auto
            cookie_samesite: lax
    
  • 添加Redis服务到你的Swarm栈(swarm_stack.yml):
    services:
        # ... 其他服务
        redis:
            image: redis:alpine
            deploy:
                replicas: 1
            volumes:
                - redis_data:/data
    volumes:
        redis_data:
    

2. 修正Swarm栈配置

去掉backend_app的ports字段,修改后的swarm_stack.yml:

services:
    nginx:
        image: ghcr.io/mygh/nginx:docker
        deploy:
            replicas: 1
        ports:
            - "80:80"
            - "443:443"

    backend_app:
        image: ghcr.io/mygh/backend:docker
        deploy:
            replicas: 2
        # 移除ports字段,避免端口冲突

    redis:
        image: redis:alpine
        deploy:
            replicas: 1
        volumes:
            - redis_data:/data

volumes:
    redis_data:

3. 完善Nginx反向代理配置

确保Symfony能正确识别反向代理的请求,避免安全验证失败,修改nginx.conf:

server {
    listen              80;
    listen              443 ssl;
    server_name  backendapp.com;

    # HTTPS相关配置(如果启用)
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://backend_app:80/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        # 添加协议头,让Symfony知道请求是HTTP还是HTTPS
        proxy_set_header X-Forwarded-Proto $scheme;
        # 修正重定向地址
        proxy_redirect off;
    }
}

同时在Symfony的config/packages/framework.yaml里配置信任反向代理:

framework:
    trusted_proxies: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
    # 或者直接信任Nginx服务的IP,不过用Swarm的子网更通用

验证

重新部署栈:

docker stack deploy -c swarm_stack.yml your_stack_name

部署后测试登录,多副本环境下会话会统一存储在Redis中,无论请求落到哪个容器都能读取到会话,登录状态就能保持了。

内容的提问来源于stack exchange,提问作者BazylPL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:40:02