本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)html
本文做者: 蘇洋前端
建立時間: 2020年05月20日 統計字數: 5171字 閱讀時間: 11分鐘閱讀 本文連接: soulteary.com/2020/05/20/…nginx
Nginx 是一款你們平常再熟悉不過的軟件,穩定高效是這款軟件的標籤。常見 Nginx 會作爲地址轉發服務或提供文件託管能力。可是 Nginx 的用法其實不止於此,原生 Nginx 還有許多實用的功能,可以實現一些業務中麻煩的小細節。git
本文將介紹三種基礎用法,若是你熟悉 Nginx 和容器,閱讀時間大概是五分鐘。github
本次使用的示例環境,均使用容器進行模擬。若是你對容器還不是很熟悉,歡迎瀏覽以前的Docker 相關文章內容。docker
一些前端類的容器,自己並無服務能力,可是爲了可以享受容器服務的基礎健康檢查,以及提供給外部諸如負載均衡等服務使用,咱們可能不得不啓動一個語言運行時,好比 Node / PHP / Java,不過若是你使用 Nginx 做爲前端使用的 Web 服務軟件,他自己就自帶了基礎的路由功能和定製響應碼和內容的能量,能夠避免咱們引入龐大的語言運行時。shell
咱們只須要在配置內添加一個名爲 /health
的路由,而後配合 default_type
和 return
指令就能夠完成咱們想要的「當服務健康時,返回HTTP CODE 200,並輸出一些內容」。編程
server {
listen 80;
location = /health {
access_log off;
default_type text/html;
return 200 'alive';
}
}
複製代碼
你或許會說,咱們可讓健康檢查軟件檢查業務路由,可是我想告訴你的是,當咱們把路由獨立以後,你會發現健康檢查的響應時間更快了,除此以外,咱們還能夠對日誌進行丟棄。若是你將健康檢查路由和業務路由放在一塊兒,海量的健康檢查日誌和業務日誌在一塊兒,會讓你調試的時候痛不欲生。跨域
配合 compose 進行健康檢查也很容易:bash
version: "3.6"
services:
health.test.soulteary.com:
image: nginx:1.18.0-alpine
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf:ro
healthcheck:
# 老版本使用
# test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:80/health || exit 1"]
test: ["CMD-SHELL", "curl -f localhost/health || exit 1"]
interval: 3s
retries: 12
複製代碼
當你使用 docker ps
查看容器進程的時候,你會看到咱們的容器會標記爲「healthy」,以後能夠配合各類策略進行容器服務基礎容災等基本操做。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2afd71cd562e nginx:1.18.0-alpine "nginx -g 'daemon of…" 10 minutes ago Up 3 seconds (healthy) 80/tcp health.test.soulteary.com_1
複製代碼
平常開發過程當中,在遇到「前端跨域」、「短信模版中連接固定」、「既有程序調用來源限制」等場景下,會遇到須要聚合站點域名或路徑的狀況。
咱們知道使用編程語言,能夠實現遠程內容獲取和轉寫,可是實際上使用 Nginx 的反向代理功能能夠更加輕鬆地作到內容聚合。
好比,在作內容聚合前,咱們須要訪問的內容在 apple.test.soulteary.com 和 banana.test.soulteary.com ,而咱們但願聚合後的內容在 test.soulteary.com 中展現。
爲了方便模擬環境,咱們先建立一個 compose 配置文件:
version: "3.6"
services:
test.soulteary.com:
image: nginx:1.18.0-alpine
ports:
- 8080:8080
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf:ro
apple.test.soulteary.com:
image: nginx:1.18.0-alpine
volumes:
- ./apple.test.soulteary.com.conf:/etc/nginx/conf.d/default.conf:ro
banana.test.soulteary.com:
image: nginx:1.18.0-alpine
volumes:
- ./banana.test.soulteary.com.conf:/etc/nginx/conf.d/default.conf:ro
複製代碼
配置文件中的 services 的三個子項分別表明聚合後的站點,以及兩個須要被聚合的站點,能夠想象爲現實中網絡相通的三臺服務器。
繼續建立 apple.test.soulteary.com.conf
這個 Nginx 配置文件。
server {
listen 80;
server_name apple.test.soulteary.com;
default_type text/html;
location / {
return 200 'apple.test.soulteary.com';
}
}
複製代碼
能夠看到,站點功能很簡單,訪問 /
的時候,返回 HTTP CODE 200,並輸出文本內容 apple.test.soulteary.com
,同理咱們建立另一個站點的 Nginx 配置文件 banana.test.soulteary.com
。
最後,建立用於聚合配置文件的 Nginx 配置。
server {
listen 8080;
server_name test.soulteary.com;
location = / {
return 302 /apple;
}
location /apple {
proxy_pass http://apple.test.soulteary.com/;
proxy_set_header Host "apple.test.soulteary.com";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /banana {
proxy_pass http://banana.test.soulteary.com/;
proxy_set_header Host "banana.test.soulteary.com";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
複製代碼
能夠看到配置十分簡單,經過 proxy_pass
配合 proxy_set_header
兩個指令,咱們就將不一樣站點聚合到了一塊。
將 test.soulteary.com
綁定至本地,而後啓動服務,使用命令行訪問站點,能夠看到配置符合預期。
# curl http://test.soulteary.com:8080/apple
apple.test.soulteary.com
# curl http://test.soulteary.com:8080/banana
banana.test.soulteary.com
複製代碼
Nginx 除了可以處理 HTTP 請求外,對於 TCP 類型的數據同樣能作到聚合/轉發。好比這裏咱們想將生產環境的某臺 GitLab 的訪問權限限制到具體的 IP,除了使用雲平臺的防火牆規則外,使用 Nginx 同樣能夠作到。
這裏要使用的是 Nginx 的 ngx_stream_proxy_module
模塊。
Nginx 容器默認配置僅包含了 HTTP 服務模式,因此此次修改不能和上面同樣,僅修改 「vhost」 配置,須要修改 nginx.conf 主配置,在修改以前,咱們先使用腳本看看默認的配置長什麼樣。
docker run --rm -it nginx:1.18.0-alpine cat /etc/nginx/nginx.conf
複製代碼
執行上面的命令,能夠看到默認的配置很簡單:
user nginx;
worker_processes auto;
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;
log_format main '$remote_addr - $remote_user [$time_local] "$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;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
複製代碼
爲了可以讓讀者輕鬆驗證,咱們假設目標倉庫是 GitHub,在對配置文件簡單修改後:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
stream{
server{
listen 2223;
proxy_pass github.com:22;
proxy_connect_timeout 10s;
proxy_timeout 20s;
proxy_buffer_size 512k;
}
}
複製代碼
咱們繼續建立一個 compose
配置文件:
version: "3.6"
services:
proxy-git.test.soulteary.com:
image: nginx:1.18.0-alpine
ports:
- 2223:2223
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
複製代碼
使用 docker-compose up
將服務啓動以後,咱們使用經典的 Git 測試命令行對服務進行驗證:
# ssh -T git@127.0.0.1 -p 2223
The authenticity of host '[127.0.0.1]:2223 ([127.0.0.1]:2223)' can't be established. RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[127.0.0.1]:2223' (RSA) to the list of known hosts. Hi soulteary! You've successfully authenticated, but GitHub does not provide shell access.
複製代碼
你會發現此刻咱們想要的目標已經達到了,不信的話,你可使用相同命令去測試下原始 Git 服務地址。
# ssh -T git@github.com
Hi soulteary! You've successfully authenticated, but GitHub does not provide shell access. 複製代碼
小節開始前提過,想進行來源限制,能夠搭配 Nginx 原生的 allow
/ deny
指令來完成:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
複製代碼
Nginx 好玩、實用的用法其實還有很多,時間緣由,就不在此展開了。
--EOF
我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。
在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。
喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)