nginx 是一個高效能的開源反向代理伺服器和 web 伺服器,一般用來搭建靜態資源伺服器、負載均衡器、反向代理,本文將分享其在 Windows/docker 中的使用,使用 nssm 部署成服務的方案指令碼,區域網中自定義域名解決https提示不安全的解決方案,以及一路踩過的坑。
設定域名轉發到專案服務
外網穿透請求轉發到區域網伺服器
測試環境專案的 https 設定
需要明白 nginx 預設啟動後會發生什麼?
Windows 中路徑需要使用 / 或者 \,如路徑 D:\Software\nginx-1.24.0\ssl
nginx.conf 需要設定為 D:/Software/nginx-1.24.0/ssl/
或 D:\Software\nginx-1.24.0\ssl\
本文版本:v1.24.0
使用埠:80 443
最基本組成:一個 server 節點一個域名設定,要新增其他設定新增 server 節點即可
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
```
直接官網下載即可 v1.24.0
下載後解壓到:D:\Software\nginx-1.24.0
在目錄輸入框開啟 cmd 並執行:start nginx
執行 nginx,如果埠沒有被佔用的話存取 localhost 即可出現 welcome 頁面
嘗試修改設定:D:\Software\nginx-1.24.0\confi\nginx.conf 新增一個文字返回
新增的文字及 json 返回
#server{....
#返回文字
location /text {
add_header Content-Type text/plain;
return 200 'This is a plain text response.';
}
#返回json
location /json {
add_header Content-Type application/json;
return 200 '{"message": "This is a JSON response.233"}';
}
#預設設定
location / {
root html;
index index.html index.htm;
}
#...}
```
因在本地測試,所以需要使用域名存取到 nginx,需要設定 hosts(伺服器外網域名設定就將域名解析到伺服器)
新增一條記錄: 127.0.0.1 ``nginx.devops.test.com
現在預設就存取nginx.devops.test.com
的時候就請求到了 nginx 的預設設定了,nginx 預設監聽了 localhost:80 使其返回我們指定的內容
新增 server 設定節點,過載設定後存取,即可看到存取顯示了設定中的內容
server {
listen 80;
server_name nginx.devops.test.com;
location / {
add_header Content-Type text/plain;
return 200 'nginx.devops.test.com';
}
}
```
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e62a40257ae548b29b9fab8389027ad5~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=359&h=23&s=1371&e=png&b=0c0c0c)
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d33c2a30c4e14bd68faacd92ac8330d8~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=410&h=122&s=6676&e=png&b=fcfcfc)
因為瀏覽器的一些機制,可能會自己預設跳轉到 https,然後還看不到協定,此時就需要手動改下
為了給網站加把鎖(資料傳輸的私密性),一般個人專案用免費的就行,不過有限制,比如萬用字元、有效期、安全性等,企業一般會使用付費證書,自行購買即可,一般雲商也會提供免費證書,其他免費的目前使用過的就下面兩種
如果本地也需要使用 https 的話,也可以通過 nginx 來設定證書,為應用加把鎖。伺服器的證書設定使用上面兩種生成,參考下面設定即可
#依次執行,輸入資訊,我這裡都輸入了 ym
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl genrsa -out ca.key 1024
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
生成 CA 證書(所在目錄:D:/Software/nginx-1.24.0/ssl)
winpty openssl genrsa -des3 -out myCA.key 2048
winpty openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem
```
匯入 myCA.pem 證書到受信任的根證書頒發機構(Win+R 開啟:certlm.msc
)
建立 CA 簽名證書(不同域名建立不同的證書)
winpty openssl genrsa -out nginx.devops.test.com.key 2048
winpty openssl req -new -key nginx.devops.test.com.key -out nginx.devops.test.com.csr
建立 X509 V3 證書擴充套件組態檔 nginx.devops.test.com。ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = nginx.devops.test.com
```
生成證書
winpty openssl x509 -req -in nginx.devops.test.com.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out nginx.devops.test.com.crt -days 825 -sha256 -extfile nginx.devops.test.com.ext
```
設定 nginx
server {
listen 80;
listen 443 ssl;
server_name nginx.devops.test.com;
ssl_certificate D:/Software/nginx-1.24.0/ssl/nginx.devops.test.com.crt;
ssl_certificate_key D:/Software/nginx-1.24.0/ssl/nginx.devops.test.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
add_header Content-Type text/plain;
return 200 'nginx.devops.test.com666';
}
}
```
成功,沒有不安全字樣了
如果要在區域網其他機器存取,也需要執行第 2 步操作匯入 myCA.pem 證書,並設定對應的 hosts
每次改完設定還要敲命令重啟,開機還要啟動,那很明顯是不太方便的,所以部署 nginx 服務就很有必要了
和 Windows 計劃任務設定開機啟動相比,我更傾向和習慣於使用 nssm (一個服務封裝程式,它可以方便的將程式封裝成 windows 服務執行)來為應用建立一個服務進行管理。
下面分享兩個快速建立服務的指令碼及使用。通過這兩個指令碼,只需修改對應路徑,就可以為應用建立服務並做到開機自啟了
新增一個啟動 nginx 的指令碼 start.bat
@echo off
cd /d %~dp0
echo kill nginx
taskkill /fi "imagename eq nginx.EXE" /f
echo start nginx
start nginx
echo start nginx success
pause
將 start.bat 指令碼使用 nssm 的方式設定為服務 nssm v2.24 下載
下載後解壓:D:\Software\nssm\nssm-2.24\win64
在目錄新增 Nginx-service.bat,以快速建立並啟動 nginx 服務,根據需要修改服務名和 nginx 啟動指令碼的路徑即可
@echo off
cd /d %~dp0
nssm stop Nginx-service
nssm remove Nginx-service confirm
nssm install Nginx-service D:\Software\nginx-1.24.0\start.bat
sc start Nginx-service
pause
以管理員 身份執行,即可建立並啟動服務,
至此,電腦重啟服務也將自啟,並且還可以通過服務的重新啟動來重啟應用
啟動:start nginx
過載設定:nginx -s reload
如果出錯會回滾到上一次正確組態檔保持正常執行,可能會存在快取,Ctrl+F5 重新整理瀏覽器
停止 nginx(刪除 nginx 程序):taskkill /fi "imagename eq nginx.EXE" /f
本篇文章基於 Docker V24 及 Docker Compose V2,安裝可以參考之前的文章
映象版本:nginx:1.24.0
指定埠:80 443
指定時區:TZ : 'Asia/Shanghai'
,讓紀錄檔檔案顯示北京時間
指定掛載目錄
./config/nginx.conf:/etc/nginx/nginx.conf
:預設組態檔,會載入 conf.d 下的所有設定./config/conf.d:/etc/nginx/conf.d
:自定義組態檔./html:/usr/share/nginx/html
:預設的靜態檔案目錄./logs:/var/log/nginx
:預設的紀錄檔目錄./ssl:/ssl
:證書目錄,設定中使用 /ssl/xxx 指定設定過載:docker exec nginx_1_24 nginx -s reload
指定網路:devopsnetwork (docker network create devopsnetwork
)
目錄結構
docker compose up -d
即可version: '3.1'
services:
nginx:
image: nginx:1.24.0
container_name: nginx_1_24
restart: always
environment:
TZ : 'Asia/Shanghai'
ports:
- "80:80"
- "443:443"
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf
- ./config/conf.d:/etc/nginx/conf.d
- ./html:/usr/share/nginx/html
- ./logs:/var/log/nginx
- ./ssl:/ssl
networks:
- devopsnetwork
networks:
devopsnetwork:
external: true
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
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;
}
將前文 Windows 的設定部分修改到 default.conf 如下所示
server {
listen 80;
listen 443 ssl;
server_name nginx.devops.test.com;
ssl_certificate /ssl/nginx.devops.test.com.crt;
ssl_certificate_key /ssl/nginx.devops.test.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
add_header Content-Type text/plain;
return 200 'nginx.devops.test.com 001';
}
}
上傳生成的 ssl 證書或者在 linux 中使用上面 openssl 的方式重新生成域名證書,然後本地新增 pem 證書,即可使用 https
要想在區域網使用自定義的域名存取應用,需要先設定 hosts 檔案,這裡使用 hosts 將域名請求指向目標伺服器 192.168.123.214
192.168.123.214 apollo.devops.test.com
192.168.123.214 rabbitmq.devops.test.com
還可以搭建一個 dns 服務,設定本機的 dns,即可將域名請求交友 dns 解析到對應服務,並且能夠實現泛解析
Apollo 面板地址:http://192.168.123.214:8070/
設定域名:apollo.devops.test.com
對應 server 設定,因為同屬一個網路,所以使用容器名加埠存取即可
server {
listen 80;
server_name apollo.devops.test.com;
location / {
proxy_pass http://apollo_portal_2_1:8070/;
#上游主機名
proxy_set_header Host $host;
# 使用者端傳送的原始主機名
#proxy_set_header host $http_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;
}
}
```
Apollo 設定 https,並重定向 http 到 https
server {
listen 80;
server_name apollo.devops.test.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name apollo.devops.test.com;
ssl_certificate /certs/apollo.devops.test.com/server.crt;
ssl_certificate_key /certs/apollo.devops.test.com/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://apollo_portal_2_1:8070/;
proxy_set_header host $http_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;
}
}
```
RabbitMQ 面板地址:http://192.168.123.214:15672/
設定域名:rabbitmq.devops.test.com
對應 server 設定,因為同屬一個網路,所以使用容器名加埠存取即可
server {
listen 80;
server_name rabbitmq.devops.test.com;
location / {
proxy_pass http://rabbitmq_3_12:15672/;
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;
}
}
```
RabbitMQ 設定 https,並重定向 http 到 https
server {
listen 80;
server_name rabbitmq.devops.test.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name apollo.devops.test.com;
ssl_certificate /certs/apollo.devops.test.com/server.crt;
ssl_certificate_key /certs/apollo.devops.test.com/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://apollo_portal_2_1:8070/;
proxy_set_header host $http_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;
}
}
```
指令碼本地目錄預覽,新增了系統判斷 linux,執行需要給要執行的指令碼新增執行許可權:chmod +x ./01.build-pem.sh
nginx-start.bat :刪除 nginx 程序並啟動 nginx 服務
@echo off
cd /d %~dp0
echo kill nginx
taskkill /fi "imagename eq nginx.EXE" /f
echo start nginx
start nginx
echo start nginx success
pause
```
nginx-nssm-service.bat 建立 nginx 服務指令碼
@echo off
cd /d %~dp0
nssm stop Nginx-service
nssm remove Nginx-service confirm
nssm install Nginx-service D:\Software\nginx-1.24.0\start.bat
sc start Nginx-service
pause
```
01.build-pem.sh 建立自簽證書
#!/bin/sh
# 生成根證書,存取使用者端需要安裝匯入 myCA.pem,根據myCA.key,myCA.pem再生成nginx需要的證書
if uname | grep -q "MINGW"; then
winpty openssl genrsa -out myCA.key 2048
winpty openssl req -x509 -new -nodes -key myCA.key -days 1825 -out myCA.pem
else
openssl genrsa -out myCA.key 2048
openssl req -x509 -new -nodes -key myCA.key -days 1825 -out myCA.pem
fi
```
02.build-ssl.sh 建立域名證書
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Usage: Must supply a domain"
exit 1
fi
DOMAIN=$1
mkdir $DOMAIN
#!/bin/sh
if uname | grep -q "MINGW"; then
winpty openssl genrsa -out $DOMAIN/server.key 2048
winpty openssl req -new -key $DOMAIN/server.key -out $DOMAIN/server.csr
else
openssl genrsa -out $DOMAIN/server.key 2048
openssl req -new -key $DOMAIN/server.key -out $DOMAIN/server.csr
fi
cat >$DOMAIN/server.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
EOF
if uname | grep -q "MINGW"; then
winpty openssl x509 -req -in $DOMAIN/server.csr -CA ./myCA.pem -CAkey ./myCA.key -CAcreateserial -out $DOMAIN/server.crt -days 36500 -extfile $DOMAIN/server.ext
else
openssl x509 -req -in $DOMAIN/server.csr -CA ./myCA.pem -CAkey ./myCA.key -CAcreateserial -out $DOMAIN/server.crt -days 36500 -extfile $DOMAIN/server.ext
fi
```
03.gen.sh 先建立自簽證書,再執行 gen.sh 生成需要的域名證書,設定到 nginx 即可
#!/bin/bash
# 獲取當前指令碼所在目錄
script_dir=$(dirname "$0")
sh $script_dir/02.build-ssl.sh nginx.devops.test.com
sh $script_dir/02.build-ssl.sh apollo.devops.test.com
sh $script_dir/02.build-ssl.sh rabbitmq.devops.test.com
```
目前只能通過taskkill /fi "imagename eq nginx.EXE" /f
刪除程序再啟動
winpty openssl
一開始是執行 openssl genrsa -out server.key 2048
命令卡死
後面找到一篇文章說是 git bash 密碼的問題,加了密碼引數確實可以了:openssl genrsa -des3 -out myCA.key -passout pass:mima 2048
但是後續使用 openssl req
還是卡死,
最後解決自簽證書授信的時候才發現是需要加上 winpty 使用才是正解
生產對應域名的證書,並在使用者端安裝證書,找到的 解決方案 ,以及思路來源 stackoverflow
不同的版本可能預設設定不一樣,可以先不掛載設定把容器的預設組態檔複製出來,在預設設定基礎上進行修改,可少走彎路。尤其如果是將 Windows 上面 的設定修改到容器中,需要注意路徑問題。
比如 windows 中設定靜態站點根目錄:root html;
,在容器中則需要設定為root /usr/share/nginx/html;
才生效
docker exec nginx_1_24 nginx -s reload
一直都是用到了就搜尋,此番整理,加深使用,以備後用
最深刻的是本篇對區域網自定義域名不安全https提示問題的解決,簡直賞心悅目。