問題描述
我有一個(gè)包含 nginx 和 PHP 的堆棧,可以在 Docker Swarm 集群上運(yùn)行.
I have a stack with nginx and PHP to run on Docker Swarm Cluster.
在我的 PHP 應(yīng)用程序中,我需要從訪問我的 web 應(yīng)用程序的客戶端主機(jī)獲取包含真實(shí) IP 的 remote_addr ($_SERVER['REMOTE_ADDR']).
In a moment in my PHP application, I need to get the remote_addr ($_SERVER['REMOTE_ADDR']) which contains the real IP from the client host accessing my webapp.
但問題是docker swarm集群通知nginx的IP.它顯示了一個(gè)像 10.255.0.2 這樣的內(nèi)部 IP,但真正的 IP 是來自客戶端主機(jī)的外部 IP(如 192.168.101.151).
But the problem is that the IP informed for nginx by docker swarm cluster. It's showed an Internal IP like 10.255.0.2, but the real IP it's the external IP from the client Host (like 192.168.101.151).
我該如何解決?
我的 docker-compose 文件:
My docker-compose file:
version: '3'
services:
php:
image: php:5.6
volumes:
- /var/www/:/var/www/
- ./data/log/php:/var/log/php5
networks:
- backend
deploy:
replicas: 1
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- /var/www/:/var/www/
- ./data/log/nginx:/var/log/nginx
networks:
- backend
networks:
backend:
我的 default.conf (vhost.conf) 文件:
My default.conf (vhost.conf) file:
server {
listen 80;
root /var/www;
index index.html index.htm index.php;
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log error;
location / {
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;
try_files $uri $uri/ /index.php;
}
location = /50x.html {
root /var/www;
}
# set expiration of assets to MAX for caching
location ~* .(js|css|gif|png|jp?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|oex|xpi|safariextz|vcf)(?[0-9]+)?$ {
expires max;
log_not_found off;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass php:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_read_timeout 300;
}
}
我的 nginx 配置文件:
My nginx config file:
user nginx;
worker_processes 3;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
keepalive_timeout 15;
client_body_buffer_size 100K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
gzip on;
gzip_comp_level 2;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/x-javascript text/xml text/css application/xml;
log_format main '$remote_addr - $remote_user [$time_local] "$request_filename" "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
include /etc/nginx/conf.d/*.conf;
}
推薦答案
對于那些不想閱讀所有 github 線程的人 ( https://github.com/moby/moby/issues/25526 ),對我有用的答案是將配置更改為:
for those don't want to read all the github thread ( https://github.com/moby/moby/issues/25526 ), the answer that was good for me was to change the config to this :
version: '3.7'
services:
nginx:
ports:
- mode: host
protocol: tcp
published: 80
target: 80
- mode: host
protocol: tcp
published: 443
target: 81
這仍然可以讓內(nèi)部覆蓋網(wǎng)絡(luò)工作,但使用 iptables 的一些技巧將這些端口直接轉(zhuǎn)發(fā)到容器,以便容器內(nèi)的服務(wù)看到數(shù)據(jù)包的正確源 IP 地址.
This still lets the internal overlay network work, but uses some tricks with iptables to forward those ports directly to the container, so the service inside the container see the correct source IP address of the packets.
iptables 中沒有允許在多個(gè)容器之間平衡端口的功能,因此您只能將一個(gè)端口分配給一個(gè)容器(其中包括一個(gè)容器的多個(gè)副本).
There is no facility in iptables to allow balancing of ports between multiple containers, so you can only assign one port to one container (which includes multiple replicas of a container).
這篇關(guān)于Docker Swarm 在 Nginx 中獲取真實(shí) IP(客戶端主機(jī))的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!