前言 为什么要做子域名配置

假设一个服务器上在不同端口各存在一个网络服务。例如:域名为 example.com,服务器上 localhost:2236 提供博客服务,localhost:2237提供其它的服务,等等。相较于输入不同的端口,我们可能更倾向于输入子域名来达到访问不同服务的目的。例如 blog.example.com 指向 localhost:2236; other.example.com 指向 localhost:2237。但域名的解析服务不支持直接对端口的解析。

一般来说,实际不同的网络服务会拆分到不同的服务器上,但是由于,我也只能用着腾讯云一年108块的廉价服务器搭自己的服务端,那么要怎么把不同的端口配置到我们解析的子域名上呢,了解到Nginx有proxy_pass的功能之后,可以用Nginx来解决这个问题。

配置步骤

1 添加子域名的解析服务

首先要在你的域名解析记录上添加子域名的解析,全部指向你的目标服务器,这里我用的是腾讯云的域名,解析记录设置参考如下图,其中记录值全部填写相同的服务器公网IP地址。

解析记录设置

2 配置Nginx

这里我的服务器使用Docker容器来运行Nginx,并且为了SSL证书,使用的是OHTTPS官方的修改版Nginx镜像,不过在配置上和常规Nginx没有区别。

首先我默认你已经用Nginx构建好了自己的一个静态页面,同时配置好了SSL证书,下面的讲解都会在443端口接受HTTPS。

首先找到你的Nginx的配置文件nginx.conf,一般在/etc/nginx目录下,我们主要关注http块下的内容,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
http {
#
server {
listen 443 ssl;
server_name blog.madsam.work;
# SSL

include /etc/nginx/default.d/*.conf;

location / {
root /usr/share/nginx/html;
index index.html;
}

error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

server {
listen 443 ssl;
server_name api.madsam.work;
# SSL

location / {
proxy_pass http://YOUR_IP_ADDRESS:PORT;
proxy_redirect off;
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80;
server_name _;
rewrite ^(.*)$ https://$host$1 permanent;
}

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;
}

上面的配置文件中,去掉了SSL证书和服务器公网IP相关的部分,我们拿第一个server块来举例,这是一个配置nginx静态页面到子域名的模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 443 ssl;
server_name blog.madsam.work;
# SSL

include /etc/nginx/default.d/*.conf;

location / {
root /usr/share/nginx/html;
index index.html;
}

# ERROR PAGE
}

这里第一个关键配置项是server_name,结合下面的location决定了nginx要在哪个子域名呈现哪个静态页面。

接下来我们再假设有一个SpringBoot服务端接口项目运行在同一个服务器的2222接口,那就是第二个server块的配置模式,利用了nginx的proxy_pass功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 443 ssl;
server_name api.madsam.work;
# SSL

location / {
proxy_pass http://YOUR_IP_ADDRESS:PORT;
proxy_redirect off;
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

也很简单,还是在server_name项输入相关的子域名,这里在proxy_pass处输入原始的baseURL,例如你有一个login接口为http://44.222.6.111:2222/login,那么在proxy_pass项中输入http://44.222.6.111:2222即可。

这里由于使用的是接口服务,意味着请求类型和请求体是不能出问题的,但是nginx在重定向的时候会使用301,也就是说如果访问端错误地从80端口提交请求,那么重定向的过程会导致请求全部变成GET,从而丢失请求体。一个解决方案是在80端口使用rewrite+保持请求状态,如下例。

1
2
3
4
5
server {
listen 80;
server_name _;
rewrite ^(.*)$ https://$host$1 permanent;
}

当然也可以多加一个80端口的匹配,再做一次proxy_pass。

完成之后可以重启nginx看是否配置成功。

另外如果你对nginx的proxy_pass配置感兴趣,例如想从nginx端实现错误请求的拦截等,可以看下面的更详细的全面讲解,这里就不多赘述了。

Nginx: Everything about proxy_pass - DEV Community