Symfony 应用程序无法获得 Traefik 和 Nginx 代理背后的 HTTPS 流量
Symfony app not getting HTTPS traffic behind Traefik and Nginx proxy
我目前尝试在 Docker 设置中部署 Symfony 应用程序。当前设置是:
[ Traefik ] -> [ Nginx ] -> [ PHP-FPM ]
- Traefik 是入口点,处理 SSL 证书(使用
dnsChallenge
选项)。
- Nginx 处理静态文件(资产和其他东西)的服务,有一个
traefik.frontend.rule
作为 label
分配域
- PHP-FPM运行PHP代码
Traefik
生成的证书没有任何问题,例如。 Traefik Dashboard 和 Portainer 工作没有任何问题。但是,当我通过浏览器访问 Symfony 应用程序时,Symfony 认为它不在 HTTPS 连接上。浏览器中的 url 字段中有 https://foo.example.tld
,但 Symfony 控制的内容回落到 http
,例如。使用绝对路径生成的图像资产或 urls。
var_dump($request->getScheme(), $request->getSchemeAndHttpHost()); // 'http' and 'http://example.tld'
我猜这是有道理的,因为 Traefik
和 Nginx
之间的连接正在使用端口 80。如果我将端口 443 分配给 Nginx
并且 Nginx
听那个而不是端口 80,我得到相同的结果。
所以问题是,我该如何解决这个问题?我是否必须生成本地 SSL 证书,让 Nginx
加载它并告诉 Traefik
使用它?还有别的办法吗?我是否需要在 Traefik
或 Nginx
上转发任何其他内容
// docker-compose.yml (shortened)
version: '3.7'
services:
traefik:
image: traefik:1.7
container_name: traefik
command: --api --docker --docker.exposedbydefault=false
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.prod.toml:/traefik.toml
- acme-storage:/acme:rw
labels:
- traefik.enable=true
- traefik.backend=medison-traefik
- traefik.frontend.rule=Host:dashboard.example.tld
- traefik.port=8080
restart: always
webserver:
image: nginx:alpine
container_name: webserver
volumes:
- ./storage/uploads:/var/www/html/web/uploads:ro
- ./config/nginx.prod.conf:/etc/nginx/conf.d/default.conf:ro
working_dir: /var/www/html/web
depends_on:
- php-fpm
labels:
- traefik.enable=true
- traefik.backend=webserver
- traefik.frontend.rule=Host:foo.example.tld
restart: always
php-fpm:
image: user/image:master
container_name: php-fpm
volumes:
- ./storage/uploads:/var/www/html/web/uploads:rw
- ./logs/php:/var/www/var/logs:rw
working_dir: /var/www/html/web
restart: always
volumes:
acme-storage:
// nginx.prod.conf
server {
listen 80 default;
client_max_body_size 108M;
access_log /var/log/nginx/application.access.log;
root /var/www/html/web;
index app.php;
if (!-e $request_filename) {
rewrite ^.*$ /app.php last;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index app.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
为了测试443端口,我在nginx.prod.conf
第2行listen 80 default;
改成了listen 443 default;
,在[=33之后添加了- traefik.port=443
到docker-compose.yml
=]
当我使用 Ingress 将项目移动到 kubernetes 时,我在从 https 重定向到 http 时遇到了同样的问题。
我设置了受信任的代理来请求。这很有帮助。
https://symfony.com/doc/4.4/deployment/proxies.html
// public/index.php
// ...
Request::setTrustedProxies(
// trust *all* requests (the 'REMOTE_ADDR' string is replaced at
// run time by $_SERVER['REMOTE_ADDR'])
['127.0.0.1', 'REMOTE_ADDR'],
// if you're using ELB, otherwise use a constant from above
Request::HEADER_X_FORWARDED_AWS_ELB
);
我目前尝试在 Docker 设置中部署 Symfony 应用程序。当前设置是:
[ Traefik ] -> [ Nginx ] -> [ PHP-FPM ]
- Traefik 是入口点,处理 SSL 证书(使用
dnsChallenge
选项)。 - Nginx 处理静态文件(资产和其他东西)的服务,有一个
traefik.frontend.rule
作为label
分配域 - PHP-FPM运行PHP代码
Traefik
生成的证书没有任何问题,例如。 Traefik Dashboard 和 Portainer 工作没有任何问题。但是,当我通过浏览器访问 Symfony 应用程序时,Symfony 认为它不在 HTTPS 连接上。浏览器中的 url 字段中有 https://foo.example.tld
,但 Symfony 控制的内容回落到 http
,例如。使用绝对路径生成的图像资产或 urls。
var_dump($request->getScheme(), $request->getSchemeAndHttpHost()); // 'http' and 'http://example.tld'
我猜这是有道理的,因为 Traefik
和 Nginx
之间的连接正在使用端口 80。如果我将端口 443 分配给 Nginx
并且 Nginx
听那个而不是端口 80,我得到相同的结果。
所以问题是,我该如何解决这个问题?我是否必须生成本地 SSL 证书,让 Nginx
加载它并告诉 Traefik
使用它?还有别的办法吗?我是否需要在 Traefik
或 Nginx
// docker-compose.yml (shortened)
version: '3.7'
services:
traefik:
image: traefik:1.7
container_name: traefik
command: --api --docker --docker.exposedbydefault=false
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.prod.toml:/traefik.toml
- acme-storage:/acme:rw
labels:
- traefik.enable=true
- traefik.backend=medison-traefik
- traefik.frontend.rule=Host:dashboard.example.tld
- traefik.port=8080
restart: always
webserver:
image: nginx:alpine
container_name: webserver
volumes:
- ./storage/uploads:/var/www/html/web/uploads:ro
- ./config/nginx.prod.conf:/etc/nginx/conf.d/default.conf:ro
working_dir: /var/www/html/web
depends_on:
- php-fpm
labels:
- traefik.enable=true
- traefik.backend=webserver
- traefik.frontend.rule=Host:foo.example.tld
restart: always
php-fpm:
image: user/image:master
container_name: php-fpm
volumes:
- ./storage/uploads:/var/www/html/web/uploads:rw
- ./logs/php:/var/www/var/logs:rw
working_dir: /var/www/html/web
restart: always
volumes:
acme-storage:
// nginx.prod.conf
server {
listen 80 default;
client_max_body_size 108M;
access_log /var/log/nginx/application.access.log;
root /var/www/html/web;
index app.php;
if (!-e $request_filename) {
rewrite ^.*$ /app.php last;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index app.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
为了测试443端口,我在nginx.prod.conf
第2行listen 80 default;
改成了listen 443 default;
,在[=33之后添加了- traefik.port=443
到docker-compose.yml
=]
当我使用 Ingress 将项目移动到 kubernetes 时,我在从 https 重定向到 http 时遇到了同样的问题。
我设置了受信任的代理来请求。这很有帮助。
https://symfony.com/doc/4.4/deployment/proxies.html
// public/index.php
// ...
Request::setTrustedProxies(
// trust *all* requests (the 'REMOTE_ADDR' string is replaced at
// run time by $_SERVER['REMOTE_ADDR'])
['127.0.0.1', 'REMOTE_ADDR'],
// if you're using ELB, otherwise use a constant from above
Request::HEADER_X_FORWARDED_AWS_ELB
);