编程崽

登录

一叶在编程苦海沉沦的扁舟之上,我是那只激情自射的崽

Nginx 安装和基础使用

Nginx 安装和基础使用

工具:可视化nginx配置工具网站,可以自行可视化的配置,然后生成配置文本,粘贴到自己的服务器中使用。

安装

使用 apt-get

sh 复制代码
apt-get install nginx

使用 yum

sh 复制代码
yum install nginx 

Mac 使用 brew

首先使用下面指令,查看本机是否已经安装了 nginx,确定是否安装的可以忽略 :

sh 复制代码
brew info nginx

在第四行左右,如果显示Not installed,是本机没有安装的意思,否则会显示当前 nginx 在本机的位置。

开始正式安装:

sh 复制代码
brew install nginx

安装完成后,输入一下指令,查看 nginx 可用命令:

sh 复制代码
nginx -h

主要常用指令为以下:

sh 复制代码
nginx # 启动
nginx -s stop # 停止
nginx -s quit # 退出
nginx -s reopen # 重启
nginx -s reload # 重新加载配置文件

主要常用指令为以下

sh 复制代码
nginx -h # 查看帮助,会显示默认的配置文件 + nginx的web服务的默认位置
nginx # 启动
nginx -s stop # 停止
nginx -s quit # 退出
nginx -s reopen # 重启
nginx -s reload # 重新加载配置文件

常用配置字段说明

nginx 复制代码
# 设置一个名为 main 的日志模板
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

http {

    # 开启gzip
    gzip on;
    # 启用gzip压缩的最小文件;小于设置值的文件将不会被压缩
    gzip_min_length 1k;
    # gzip 压缩级别 1-10,值越大压缩的越厉害,也更消耗cpu,但大于6后的压缩效果就不太明显了 
    gzip_comp_level 2;
    # 进行压缩的文件类型。
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;
    sendfile        on;

    # 超时时间,默认 75 秒
    keepalive_timeout  65;
    autoindex on;  # 开启目录文件列表
    autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytes
    autoindex_localtime on;  # 显示的文件时间为文件的服务器时间
    charset utf-8,gbk;  # 避免中文乱码

    # 一个服务,一个服务对应监听一个端口号,指向一个 web 项目目录
    server {
        # 监听的端口号,http 协议都是访问 80 端口,https 是 443 端口
        listen 80;
        # 捕获的域名,可能有多个网站的服务都在这个服务器中,这里就依靠 server_name,来捕获这个 server 要提供服务的域名们
        # 下面是只有访问的域名 www.junlli.com 或 junlli.com 时,才走这个 server
        server_name www.junlli.com junlli.com;
        # 访问到这个 server 时,记录的访问日志的存放位置和使用的日志模板
        access_log  /var/log/nginx/doc.log main;
        # 关键,这个 server 指向的前端项目根目录
        root /root/www/my-doc-web/my-doc-web/build;
        # 响应时,为所有的响应头添加一个字段,下面是给所有响应都都添加缓存,单位秒
        add_header Cache-Control "max-age=31536000";
        # 主文件,当访问过来时,路由上没有指定具体访问哪个文件时,会默认返回的文件
        index index.html index.htm;
        # 应对 vue、react 这种单页项目的配置
        try_files $uri $uri/ @rewrites;
        location ~* \.(html)$ {
            # 设置所有的 html 格式的文件,前端都不进行缓存
            add_header Cache-Control "no-store, no-cache";
        }
        # 应对 vue、react 这种单页项目的配置
        location @rewrites {
            rewrite ^(.+)$ /index.html last;
        }
    }
    

    #include /var/www/**/nginx.conf; # 引入其他文件夹的nginx配置文件,引入的模式,相当于内容直接粘贴在这里
}

注意 nginx 配置中的 server_name 字段。

正常部署时,某个服务器下,可能会部署多个项目,比如 www.a.comwww.b.com 等等,他们的域名解析,都会解析到这个服务器的 ip 下,也就都会走入到这个服务器的 nginx 中。

nginx 可以配置多个 server,每个 server 就是一个网站,server 就是按照 server_name 来设置一个域名、捕获请求,并返回自己这个 server 配置的项目。

如果某个 server 配置的 server_name 为 www.a.com,那么虽然 www.a.comwww.b.com 的域名解析都到了这个服务器,但只有 www.a.com 会走到这个 server 中,其他的一律被这个 server 忽略,然后去由其他的 server 捕获。

但如果,有一个 server 没有配置 server_name,那么 nginx 也不会报错,会默认你给这个 server 设置的 server_name,是 nginx 所有 server配置中,按顺序读取到的第一个 server 的 server_name,这一点是需要注意的。

我的 Nginx 配置文件

nginx 复制代码
user root;
worker_processes 1;

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;

    # 开启gzip
    gzip on;

    # 启用gzip压缩的最小文件;小于设置值的文件将不会被压缩
    gzip_min_length 1k;

    # gzip 压缩级别 1-10,值越大压缩的越厉害,也更消耗cpu,但大于6后的压缩效果就不太明显了 
    gzip_comp_level 2;

    # 进行压缩的文件类型。
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;
    autoindex on;  # 开启目录文件列表
    autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytes
    autoindex_localtime on;  # 显示的文件时间为文件的服务器时间
    charset utf-8,gbk;  # 避免中文乱码
  
    include /var/www/**/nginx.conf;
}

vue、react等单页应用的nginx配置

由于和vue、react使用SPA,路由由vue和react管理
当vue和react使用某种路由模式时,路由和常规网站无区别,需要修改web服务器来配合 当前端访问的一个路径到达nginx,nginx需要判断访问的文件是否存在
如果存在则返回文件,如果不存在,则需要返回index.html文件,前端拿到文件后,框架的js会解析路由,进行对应的处理

vue和react的某种路由模式说明:

vue写使用Router进行配置时,设置mode字段,在访问子页面时有以下两种模式:

  • hash(默认):路由使用#拼接,好用,但是不好看
  • history:路由和常规网站路径无区别,使用斜杠/拼接,但需要进行如下的服务器配置

react的HashRouter等同于vue的hash模式,BrowserRouter相当于history模式

nginx 复制代码
# vue的history模式、react的BrowserRouter模式等单页应用的nginx配置
server {
    listen 80;
    server_name a.abc.com;
    # access_log /Users/majun/Desktop/nginx-test/log.log main;
    root /Users/majun/Desktop/nginx-test/user;
    index index.html;
  
    # 请求的就是 html 文件,有则设置响应头返回,无则去执行 @index
    location ~*\.html$ {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri @index;
    }
    # 有则返回,无则执行 @add-html
    location / {
        try_files $uri @add-html;
    }

    # 添加 index.html 后,有则设置响应头返回,无则去执行 @index
    location @add-html {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri/index.html @index;
    }

    # 要直接返回 index.html 文件了,设定响应头
    location @index {
        add_header Cache-Control "no-store, no-cache";
        rewrite ^(.+)$ /index.html last;
    }
}

配置反向代理

nginx 复制代码
# 反向代理,主要用于调用接口时的反向代理
server {
    listen 80;
    server_name b.abc.com;
    # access_log  /var/log/nginx/b.log  main;
    client_max_body_size 50m; # 文件大小限制,默认1m
  
    # 命中接口代理 去转发,可以同时使用 rewrite 重写一下请求的 url
    location / {
        proxy_pass http://localhost:8003;
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
        add_header Cache-Control "no-store, no-cache";
        rewrite "^/apis/(.*)$" /$1 break;
    }
}

配置单页面应用 + 路由项目 + 接口反向代理

下面配置一个复杂项目。

这个项目是两个前端项目,打包后分别放在 user 文件夹和 admin 文件夹,要求:

所以,我们首先要先准备好两个项目和一个接口服务(接口服务后台提供,不多讲了)。

其中,user 项目正常打包即可,打包出的静态文件们放入 user 文件夹备用,比较复杂一点的是 admin 项目。

admin 项目最终打包完成的项目,需要满足以下两点:

  1. 所有路由,都要作为 /admin 的次级路由。
  2. 打包后,index.html 中引用文件时,需要在文件路径前,额外加上 /admin

所有路由,都要作为 /admin 的次级路由

因为上面说了,访问 http://localhost:8001/admin ,访问到的是 admin/ 中文件,所以在开发时就要先做好这方面准备。

好在 vue 本身就提供这个配置,react 也有类似功能,下面以 vue 为例:

js 复制代码
// vue3 之前的配置方式
import Router from 'vue-router'
import Config from '../pages/Config.vue'

const router = new Router({
  mode: 'history',
  base: 'admin', // 这一行就是关键配置了
  routes: [{
    path: '/config',
    component: Config,
  }],
})

// vue3 的配置方式
import { createRouter, createWebHistory } from 'vue-router'
import Config from '../pages/Config.vue'

const router = createRouter({
  history: createWebHistory('/admin/'), // 这一行就是关键配置了
  routes: [{
    path: '/config',
    component: Config,
  }],
})

配置完后,会自动给所有路由前,再添加一个 /admin

比如,再访问自己的 Config 页,路由会自动跳转 http://localhost:8001/admin/config,且也只有这个路由才能访问到 Config 页,其他路由也同理。

html 中引用资源的路径前,加上 /admin

正常打包完成后,生成的 index.html 中,它引用资源会以绝对路径引用。

比如有以下目录:

sh 复制代码
./dist
├── assets
│   ├── index.js
├── favicon.ico
└── index.html

那么 index.html 中引用 js 的路径为:

html 复制代码
<script type="module" crossorigin src="/assets/index.js"></script>

但现在不行了,需要改成下面这种引用路径:

html 复制代码
<script type="module" crossorigin src="/admin/assets/index.js"></script>

而且,css 中引入图片、字体等资源,也需要同样的配置。

这是因为页面访问 http://localhost:8001/admin 时,才会访问到 admin 文件夹下,想访问到这些资源,肯定也是需要前面有 /admin。

同样,react 和 vue 的编译器,提供有这个功能,下面以 vue 为例:

js 复制代码
// 使用 webpack 作为编译工具
// vue.config.js 中
module.exports = {
  publicPath: 'admin', // 配置
}

// 使用 vite 作为编译工具
//  vite.config.js 中
import { defineConfig } from 'vite'

export default defineConfig({
  base: '/admin/',
})

有了上面的配置,再打包后,静态文件中引入资源的链接,就都有了对应修改。

最终的nginx 配置

最终的 nginx 配置如下,root 后面的路径自定

nginx 复制代码
# log_format main 'main [$request_filename] "$uri" "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';

# 主入口 server
server {
    listen 8001;
    # server_name www.abc.com abc.com;
    # access_log /Users/majun/Desktop/nginx-test/log.log main;
    root /Users/majun/Desktop/nginx-test/user; # user 项目路径
    index index.html; # 主入口文件
    add_header Cache-Control "max-age=31536000"; # 默认的响应头

    # 命中接口代理 去转发,同时使用 rewrite 重写一下请求的 url
    location ^~/apis {
        proxy_pass http://localhost:8003; # 目标地址
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
        add_header Cache-Control "no-store, no-cache"; # 设置不缓存
        rewrite "^/apis/(.*)$" /$1 break; # 使用正则重写 url,去掉 '/apis'
    }

    # 命中其他项目代理,去转发,直接代理
    location ^~/admin {
        # 这里需要把响应头的 Cache-Control 清空,否则会硬性新增到代理后的所有请求中
        add_header Cache-Control "";
        proxy_pass http://localhost:8002; # admin 项目的入口服务
    }

    # 请求的就是 html 文件,有则设置响应头返回,无则去执行 @index
    location ~*\.html$ {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri @index;
    }
    # 有则返回,无则执行 @add-html
    location / {
        try_files $uri @add-html;
    }

    # 添加 index.html 后,有则设置响应头返回,无则去执行 @index
    location @add-html {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri/index.html @index;
    }

    # 要直接返回 index.html 文件了,设定响应头
    location @index {
        add_header Cache-Control "no-store, no-cache";
        rewrite ^(.+)$ /index.html last;
    }
}

# admin 项目入口,这个端口可以不用开放外部访问的权限
server {
    listen 8002;
    # server_name www.abc.com abc.com;
    # access_log /Users/majun/Desktop/nginx-test/log.log main;
    root /Users/majun/Desktop/nginx-test/admin; # user 项目路径
    index index.html; # 主入口文件
    add_header Cache-Control "max-age=31536000"; # 默认的响应头

    # 已经到了 admin 文件夹了,去除前缀
    location ^~/admin {
        rewrite "^/admin/?(.*)$" /$1 last;
    }

    # 请求的就是 html 文件,有则设置响应头返回,无则去执行 @index
    location ~*\.html$ {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri @index;
    }
    # 有则返回,无则执行 @add-html
    location / {
        try_files $uri @add-html;
    }

    # 添加 index.html 后,有则设置响应头返回,无则去执行 @index
    location @add-html {
        add_header Cache-Control "no-store, no-cache";
        try_files $uri/index.html @index;
    }

    # 要直接返回 index.html 文件了,设定响应头(注意这里返回的是 /admin/index.html 文件)
    location @index {
        add_header Cache-Control "no-store, no-cache";
        rewrite ^(.+)$ /admin/index.html last;
    }
}

HTTPS服务配置

http自动转https

nginx 复制代码
server {
    listen 80;
    server_name www.certificatestests.com; #将www.certificatestests.com修改为您证书绑定的域名,例如:www.example.com。
    rewrite ^(.*)$ https://$host$1 permanent;   #将所有HTTP请求通过rewrite重定向到HTTPS。
}

https的server配置(来自 阿里云SSL服务配置文档

nginx 复制代码
#以下属性中以ssl开头的属性代表与证书配置有关,其他属性请根据自己的需要进行配置。
server {
    listen 443 ssl; #配置HTTPS的默认访问端口号为443。此处如果未配置HTTPS的默认访问端口,可能会造成Nginx无法启动。Nginx 1.15.0以上版本请使用listen 443 ssl代替listen 443和ssl on。
    server_name www.certificatestests.com; #将www.certificatestests.com修改为您证书绑定的域名,例如:www.example.com。如果您购买的是通配符域名证书,要修改为通配符域名,例如:*.aliyun.com。
    root html;
    index index.html index.htm;
    ssl_certificate cert/domain name.pem;  #将domain name.pem替换成您证书的文件名称。
    ssl_certificate_key cert/domain name.key; #将domain name.key替换成您证书的密钥文件名称。
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。
    ssl_prefer_server_ciphers on;
    location / {
      root html;  #站点目录。
      index index.html index.htm;
    }
}

Nginx 默认配置文件

以下为 nginx version: nginx/1.14.0 (Ubuntu) 的默认配置文件

nginx 复制代码
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
# 
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}