## 前言 如果使用 Docker Swarm 去做 Load balance 機制,當我們要取得來源端 client ip 時,會發現由 `HttpServletRequest.getHeader("X-Forwarded-For")` 所得到的 ip 會變成例如 `10.0.0.2` 這個樣子。 因為取得的是 docker 自己分派的虛擬 ip。 目前無法利用 Docker 自行解決。但是我們可以利用一台**反向代理服務**入口,再轉導至 該 Docker Swarm 入口,就可以取到正確的 ip。 ## 架構圖 ![](https://hackmd.io/_uploads/ryASNia6h.png) ## 說明 在建立 Docker Swarm 建立號服務站來後,不要以服務站台的位置當入口(10.205.60.X.7777)。而是建立一台 Reverse Proxy 當作服務露出的入口。 而這個 Reverse Proxy 不會加入該 Docker Swarm。 ## 實作 這邊先預設服務站台的 Docker Swarm 已經建立完畢。只差一個 Reverse Proxy。這邊以 Docker Nginx 為範例。 ### nginx.conf 在 `upstream` 區塊中,我們定義要反向代理轉導的伺服器位置。 `server`區塊下的 `listen` 則是該 Reverse Proxy 需要露出的 port 號。 location 後的 `/` ,指的是要轉導至 myServer 的跟目錄。( 會轉到 10.20.60.1:7777/ )。 但假如你是要轉去 myServer 的其他位置,例如`10.20.60.1:7777/api-service/somewhere`,則`location` 後方的`/`就要改成 `/api-service/somewhere` ```docker= upstream myServer { server 10.20.60.1:7777; } server { listen 443; server_name localhost; location / { #定義反向代理指定要去的位置 proxy_pass http://myServer; proxy_set_header Host $host; #讓後端的Web伺服器可以取得使用者真實IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` ### Dockerfile-nginx-proxy 直接使用的最新版本的`nginx` image,並把我們寫好的`nginx.conf`複製進去`nginx` image服務內的設定檔位置。 ```= FROM nginx COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 443 ``` ### 執行 利用 Docker 指令產生 image ``` docker build -t my_reverse_proxy:1.0.0 -f Dockerfile-nginx-proxy . ``` 之後在主機A`10.205.60.1`使用指令啟動服務 `docker run -it -d -p 10.205.60.1:443:443 --name MY_REVERSE_PROXY my_reverse_proxy:1.0.0` 這時候讓 User 使用 `10.205.60.1:443` 進入服務,後端站台就能取到真實的 Client ip 了!!