配置CodeIgniter的base_url时遇Nginx+Docker环境502网关错误
问题:Docker化CodeIgniter应用设置HTTPS base_url时出现502 Bad Gateway错误
问题描述
我有一个运行在Docker化环境(包含PHP-FPM、MySQL、Nginx)的遗留CodeIgniter应用。当将application/config/config.php中的base_url设置为IP地址或http://domain_name.example.in:8086/时应用运行正常,但设置为https://domain_name.example.in/时出现“502 Bad Gateway”错误。
环境详情
1. Docker Compose配置
version: '3.9' services: app: build: context: . dockerfile: dockerfile container_name: php-fpm volumes: - .:/var/www/html networks: - mynetwork depends_on: - db db: image: mysql:5.7 container_name: database ports: - "3308:3306" environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: test MYSQL_USER: test MYSQL_PASSWORD: password volumes: - db_data:/var/lib/mysql - ./data_dump.sql:/docker-entrypoint-initdb.d/data_dump.sql:ro networks: - mynetwork nginx: image: nginx:alpine container_name: nginx ports: - "8080:80" volumes: - ./nginx-1.17.6/conf/nginx.conf:/etc/nginx/conf.d/default.conf:ro - .:/var/www/html depends_on: - app volumes: db_data: networks: mynetwork: driver: bridge
2. PHP-FPM Dockerfile
FROM php:7.0-fpm RUN docker-php-ext-install mysqli RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev libfreetype6-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/freetype2 --with-jpeg-dir=/usr/include \ && docker-php-ext-install gd EXPOSE 9000
3. Nginx架构
- Docker容器内的Nginx监听80端口(主机映射到8080),将请求代理至PHP-FPM容器;
- 主机服务器上另有一台外部Nginx服务器,负责将请求转发至Docker化的Nginx服务器。
4. Cloudflare配置
使用Flexible SSL模式,由Cloudflare处理SSL终止,之后通过HTTP协议将流量转发至我的服务器。
问题现象
当将application/config/config.php中的base_url设置为https://domainname.in/时,触发“502 Bad Gateway”错误;设置为IP地址或http://domain_name.example.in:8086/时,应用可正常跳转并运行。
$config['base_url'] = 'https://domainname.in/';
已尝试的排查操作
- 确认Docker容器内的Nginx和主机上的外部Nginx均已正确配置请求代理规则;
- 验证Nginx和PHP-FPM的端口已开放且可正常访问;
- 检查Cloudflare的SSL设置,确认已启用Flexible SSL;
- 确认外部Nginx服务器可正确将请求转发至Docker Nginx容器;
- 检查应用和Nginx中的base URL及SSL相关配置是否正确。
疑问
- 为何设置HTTPS域名形式的
base_url会触发502错误,而IP地址或带端口的HTTP域名则正常? - 该问题是否与Cloudflare的Flexible SSL配置有关,还是Nginx配置存在错误?
- 需要对Nginx配置进行哪些特定调整,才能正确处理来自Cloudflare的HTTPS请求?
解答
1. 错误原因分析
- Cloudflare Flexible SSL的影响:Flexible模式下,Cloudflare与服务器之间用HTTP通信,但CodeIgniter设置
base_url为HTTPS后,生成的内部跳转/资源链接会是HTTPS。如果外部Nginx未正确传递X-Forwarded-Proto等头信息,会导致请求转发过程中协议不匹配,触发502错误。 - Nginx配置缺失:外部Nginx和Docker内的Nginx如果没有传递HTTPS相关请求头,PHP-FPM/CodeIgniter无法识别原始请求是HTTPS,处理时会出现异常(比如跳转循环、路由错误),最终引发502。
2. 具体修复步骤
(1)调整外部Nginx配置(接收Cloudflare请求的服务器)
在server块中添加配置,传递HTTPS相关头信息到Docker内的Nginx:
server { listen 80; server_name domainname.in; # 识别Cloudflare传递的HTTPS协议标识 set $real_proto $scheme; if ($http_x_forwarded_proto = 'https') { set $real_proto 'https'; } # 转发请求到Docker Nginx的8080端口 location / { proxy_pass http://localhost:8080; 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 $real_proto; # 关键:告诉后端原始请求协议是HTTPS } }
(2)调整Docker内的Nginx配置(代理到PHP-FPM的容器)
在处理PHP的location块中,添加传递HTTPS头到PHP-FPM的配置:
server { listen 80; root /var/www/html; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass app:9000; # 使用Docker服务名app,而非localhost fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS $http_x_forwarded_proto = 'https' ? 'on' : 'off'; # 告诉PHP请求为HTTPS fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; include fastcgi_params; } }
(3)优化CodeIgniter的base_url配置
让base_url自动识别协议,适配HTTP和HTTPS场景:
$config['base_url'] = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . '/';
若确定只有HTTPS请求(通过Cloudflare),也可保持硬编码,但必须确保Nginx已传递正确的HTTPS环境变量给PHP。
3. 验证步骤
- 重启外部Nginx:
sudo systemctl restart nginx; - 重启Docker容器:
docker-compose down && docker-compose up -d; - 访问
https://domainname.in/,检查是否仍有502错误; - 查看Nginx错误日志(外部Nginx:
/var/log/nginx/error.log,Docker内Nginx:docker exec nginx tail -f /var/log/nginx/error.log),排查具体错误信息。
内容的提问来源于stack exchange,提问作者Sandeep pradeep
相关产品推荐
相关产品推荐

