Docker Swarm在Nginx中获得真实IP(客户端主机) [英] Docker Swarm get real IP (client host) in Nginx
问题描述
我有一个包含nginx和PHP的堆栈,可在Docker Swarm Cluster上运行.
I have a stack with nginx and PHP to run on Docker Swarm Cluster.
稍后在我的PHP应用程序中,我需要获取remote_addr($ _SERVER ['REMOTE_ADDR']),其中包含来自访问我的Web应用程序的客户端主机的真实IP.
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 cluster将IP告知了nginx.它显示了一个内部IP,例如10.255.0.2,但实际IP是来自客户端主机的外部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;
}
推荐答案
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
这仍然可以使内部覆盖网络正常工作,但是使用iptables的一些技巧将这些端口直接转发到容器,因此容器内的服务会看到数据包的正确源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中没有设施来允许多个容器之间的端口平衡,因此只能将一个端口分配给一个容器(其中包括一个容器的多个副本).
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).
这篇关于Docker Swarm在Nginx中获得真实IP(客户端主机)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!