前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >通过 docker 高效学习 nginx 配置,并附全部配置文件

通过 docker 高效学习 nginx 配置,并附全部配置文件

作者头像
山月
发布于 2022-11-02 08:34:35
发布于 2022-11-02 08:34:35
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

三年经验的前端或多或少与 nginx 配置打过交道。

nginx 的重要性不言而喻。

本篇文章以前端的视角,介绍下 nginx 的常见配置,并通过 docker 的方式学习 nginx,这保证所有示例配置都能正常运行。

我将本文所有关于 docker/nginx 的配置放置在 simple-deploy1,可克隆下来通过 docker compose 快速运行。

并将所有的接口示例维护在了 Learn Nginx By Docker2 文档,并可通过 Apifox3 打开并快速调试。

nginx 的配置文件

我们通过 nginx 镜像来了解 nginx 的配置文件都有哪些。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker run -it --rm nginx:alpine sh

$ ls -lah /etc/nginx/
total 40K    
drwxr-xr-x    3 root     root        4.0K Nov 13  2021 .
drwxr-xr-x    1 root     root        4.0K Jun 14 07:55 ..
drwxr-xr-x    2 root     root        4.0K Nov 13  2021 conf.d
-rw-r--r--    1 root     root        1.1K Nov  2  2021 fastcgi.conf
-rw-r--r--    1 root     root        1007 Nov  2  2021 fastcgi_params
-rw-r--r--    1 root     root        5.2K Nov  2  2021 mime.types
lrwxrwxrwx    1 root     root          22 Nov 13  2021 modules -> /usr/lib/nginx/modules
-rw-r--r--    1 root     root         648 Nov  2  2021 nginx.conf
-rw-r--r--    1 root     root         636 Nov  2  2021 scgi_params
-rw-r--r--    1 root     root         664 Nov  2  2021 uwsgi_params

nginx 中,其中比较重要的有以下几个文件,而它们都是有层层关联的:

  • /etc/nginx/nginx.conf
  • /etc/nginx/conf.d/default.conf

/etc/nginx/nginx.conf

nginx 主配置文件,引用了 /etc/nginx/conf.d/ 目录下的所有配置文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
}

/etc/nginx/conf.d/default.conf

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server {
    listen       80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

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

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

/usr/share/nginx/html

默认的静态资源目录,也是 nginx 的欢迎页面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

通过 docker 高效学习 nginx 配置

推荐一种高效学习 nginx 的方法: 「在本地使用 nginx 镜像并挂载 nginx 配置启动容器

Learning Nginx

通过以下 docker-compose 可秒级验证 nginx 配置,无疑是学习 nginx 的绝佳利器。

「我将所有关于 nginx 的配置放置在 simple-deploy1,并且每一份配置对应 docker-compose 中的一个 service」 如以下 nginx、location、order1 就是 service

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
version: "3"
services:
  # 关于 nginx 最常见配置的学习
  nginx:
    image: nginx:alpine
    ports:
      - 8080:80
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - .:/usr/share/nginx/html
  # 关于 location 的学习
  location: ...
  # 关于 location 匹配顺序的学习
  order1: ...

每次修改配置时,需要重启容器,可根据服务名学习指定内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker-compose up <service>

# 学习 nginx 最基础的配置
$ docker-compose up nginx

# 学习关于 location 的配置
$ docker-compose up location

本篇文章所有的 nginx 配置均可以通过 docker 来进行学习,并附全部代码及配置。

root 与 index

  • root: 静态资源的根路径。见文档 https://nginx.org/en/docs/http/ngx_http_core_module.html#root
  • index: 当请求路径以 / 结尾时,则自动寻找该路径下的 index 文件。见文档 https://nginx.org/en/docs/http/ngx_http_index_module.html#index

rootindex 为前端部署的基础,在默认情况下 root 为 /usr/share/nginx/html,因此我们部署前端时,往往将构建后的静态资源目录挂载到该地址。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;
}

location

location 用以匹配路由,配置语法如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location [ = | ~ | ~* | ^~ ] uri { ... }

其中 uri 前可提供以下修饰符

  • = 精确匹配,优先级最高。
  • ^~ 前缀匹配,优先级其次。如果同样是前缀匹配,走最长路径。
  • ~ 正则匹配,优先级再次 (~* 只是不区分大小写,不单列)。如果同样是正则匹配,走第一个路径。
  • / 通用匹配,优先级再次。

为了验证所匹配的 location,我会在以下示例中添加一个自定义响应头 X-Config,可通过浏览器控制台网络面板验证其响应头。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
add_header X-Config B;

注意,我所有「配置文件中的链接可直接点击,避免了在 compose 配置文件中寻找映射端口号的不方便」

location 修饰符验证

对于此四种修饰符可以在我的 nginx 下进行验证。

由于此处使用了 proxy_pass,因此需要 location2api 两个服务一起启动,在 location2 服务中,可直接通过 service 名称作为 hostname 即 http://api:3000 访问 api 服务。

而 api 服务,为我自己写的一个 whoami 服务,用以打印出请求路径等信息,详见 shfshanyue/whoami4。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker-compose up location2 api

以下是关于验证 location 的配置文件,详见 shfshanyue/simple-daploy:learn-nginxs5

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    # 通用匹配,所有 /xxx 任意路径都会匹配其中的规则
    location / {
        add_header X-Config A;
        try_files  $uri $uri.html $uri/index.html /index.html;
    }

    # http://localhost:8120/test1           ok
    # http://localhost:8120/test1/          ok
    # http://localhost:8120/test18          ok
    # http://localhost:8120/test28          not ok
    location /test1 {
        # 可通过查看响应头来判断是否成功返回
        add_header X-Config B;
        proxy_pass http://api:3000;
    }

    # http://localhost:8120/test2           ok
    # http://localhost:8120/test2/          not ok
    # http://localhost:8120/test28          not ok
    location = /test2 {
        add_header X-Config C;
        proxy_pass http://api:3000;
    }

    # http://localhost:8120/test3           ok
    # http://localhost:8120/test3/          ok
    # http://localhost:8120/test38          ok
    # http://localhost:8120/hellotest3      ok
    location ~ .*test3.* {
        add_header X-Config D;
        proxy_pass http://api:3000;
    }

    # http://localhost:8120/test4           ok
    # http://localhost:8120/test4/          ok
    # http://localhost:8120/test48          ok
    # http://localhost:8120/test28          not ok
    location ^~ /test4 {
        # 可通过查看响应头来判断是否成功返回
        add_header X-Config E;
        proxy_pass http://api:3000;
    }
}

location 优先级验证

在我配置文件中,以 order 打头来命名所有优先级验证的 nginx 配置,总共有四个配置文件,详见 docker-compose6。

此处仅仅以 order1 为例进行验证,配置如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 以下配置,访问以下链接,其 X-Config 为多少
#
# http://localhost:8210/shanyue,为 B,若都是前缀匹配,则找到最长匹配的 location

server {
    root   /usr/share/nginx/html;

    # 主要是为了 shanyue 该路径,因为没有后缀名,无法确认其 content-type,会自动下载
    # 因此这里采用 text/plain,则不会自动下载
    default_type text/plain;

    location ^~ /shan {
        add_header X-Config A;
    }

    location ^~ /shanyue {
        add_header X-Config B;
    }
}

启动服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker-compose up order1

curl 验证:

当然也可以通过浏览器控制台网络面板验证,由于此处只需要验证响应头,则我们通过 curl --head 只发送 head 请求即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 查看其 X-Config 为 B
$ curl --head http://localhost:8210/shanyue
HTTP/1.1 200 OK
Server: nginx/1.21.4
Date: Fri, 03 Jun 2022 10:15:11 GMT
Content-Type: text/plain
Content-Length: 15
Last-Modified: Thu, 02 Jun 2022 12:44:23 GMT
Connection: keep-alive
ETag: "6298b0a7-f"
X-Config: B
Accept-Ranges: bytes

proxy_pass

proxy_pass 反向代理,也是 nginx 最重要的内容,这也是常用的解决跨域的问题。

当使用 proxy_pass 代理路径时,有两种情况

  1. 代理服务器地址不含 URI,则此时客户端请求路径与代理服务器路径相同。「强烈建议这种方式」
  2. 代理服务器地址含 URI,则此时客户端请求路径匹配 location,并将其 location 后的路径附在代理服务器地址后。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 不含 URI
proxy_pass http://api:3000;

# 含 URI
proxy_pass http://api:3000/;
proxy_pass http://api:3000/api;
proxy_pass http://api:3000/api/;

再举一个例子:

  1. 访问 http://localhost:8300/api3/hello,与以下路径匹配成功
  2. proxy_pass 附有 URI
  3. 匹配路径后多余的路径为 /hello,将其附在 proxy_pass 之后,得 http://api:3000/hello/hello
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location /api3 {
    add_header X-Config C;

    # http://localhost:8300/api3/hello -> proxy:3000/hello/hello
    proxy_pass http://api:3000/hello;
}

有点拗口,在我们试验环境有多个示例,使用以下代码启动可反复测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker-compose up proxy api

由于 proxy_pass 所代理的服务为 whoami,可打印出真实请求路径,可根据此进行测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    # 建议使用此种 proxy_pass 不加 URI 的写法,原样路径即可
    # http://localhost:8300/api1/hello -> proxy:3000/api1/hello
    location /api1 {
        # 可通过查看响应头来判断是否成功返回
        add_header X-Config A;
        proxy_pass http://api:3000;
    }

    # http://localhost:8300/api2/hello -> proxy:3000/hello
    location /api2/ {
        add_header X-Config B;
        proxy_pass http://api:3000/;
    }

    # http://localhost:8300/api3/hello -> proxy:3000/hello/hello
    location /api3 {
        add_header X-Config C;
        proxy_pass http://api:3000/hello;
    }

    # http://localhost:8300/api4/hello -> proxy:3000//hello
    location /api4 {
        add_header X-Config D;
        proxy_pass http://api:3000/;
    }
}

add_header

控制响应头。

由于很多特性都是通过响应头控制,因此基于此指令可做很多事情,比如:

  1. Cache
  2. CORS
  3. HSTS
  4. CSP
  5. ...

Cache

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location /static {
    add_header Cache-Control max-age=31536000;
}

CORS

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location /api {
    add_header Access-Control-Allow-Origin *;
}

HSTS

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location / {
    listen 443 ssl;

    add_header Strict-Transport-Security max-age=7200;
}

CSP

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
location / {
    add_header Content-Security-Policy "default-src 'self';";
}

作业

  • 初阶: 基于 docker 学习 nginx 配置,并可配置 index.html 强缓存 60s 时间
  • 中阶: 如何使用 nginx 与 whoami 镜像,模拟 502/504
  • 高阶: 基于 docker 学习 nginx 配置,并可配置 gzip/brotli
  • 面试: brotli/gzip 有何区别

参考资料

[1]

simple-deploy:https://github.com/shfshanyue/simple-deploy/tree/master/learn-nginx

[2]

Learn Nginx By Docker:https://www.apifox.cn/apidoc/project-1264553

[3]

Apifox:https://www.apifox.cn/a1shanyue

[4]

simple-deploy:https://github.com/shfshanyue/simple-deploy/tree/master/learn-nginx

[5]

shfshanyue/whoami:https://github.com/shfshanyue/whoami

[6]

shfshanyue/simple-daploy:learn-nginxs:https://github.com/shfshanyue/simple-deploy/blob/master/learn-nginx/location2.conf

[7]

docker-compose:https://github.com/shfshanyue/simple-deploy/blob/master/learn-nginx/docker-compose.yaml

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
11 条评论
热度
最新
sudo: unknown user steam sudo: error initializing audit plugin sudoers_audit 发生这两个错误怎么办?
sudo: unknown user steam sudo: error initializing audit plugin sudoers_audit 发生这两个错误怎么办?
222举报
同问同问
同问同问
回复回复1举报
为啥都不用docker呢,1s就搞定了最新解决办法我的已经搞定了:https://www.playezu.com/810853.html PalWorld 幻兽帕鲁开服(Docker版)支持升级存档
为啥都不用docker呢,1s就搞定了最新解决办法我的已经搞定了:https://www.playezu.com/810853.html PalWorld 幻兽帕鲁开服(Docker版)支持升级存档
回复回复点赞举报
2月1号的更新你们2月3号出教程,到了2月27号再次更新 页面都不一样了 怎么更?
2月1号的更新你们2月3号出教程,到了2月27号再次更新 页面都不一样了 怎么更?
回复回复1举报
在这里执行命令不用获取管理员权限了吗 也不用停止和重启游戏了吗
在这里执行命令不用获取管理员权限了吗 也不用停止和重启游戏了吗
回复回复1举报
在这里执行命令不用获取管理员权限了吗
在这里执行命令不用获取管理员权限了吗
回复回复点赞举报
windows版如果命令运行好了还是不兼容可以再执行几次命令
windows版如果命令运行好了还是不兼容可以再执行几次命令
回复回复点赞举报
回复回复点赞举报
更新好了,谢谢大佬,主要是今天一直在用公共命令里的那个更新,一直执行失败
更新好了,谢谢大佬,主要是今天一直在用公共命令里的那个更新,一直执行失败
11点赞举报
哈哈多谢,欢迎来交流群帮更多的人成功更新游戏。
哈哈多谢,欢迎来交流群帮更多的人成功更新游戏。
回复回复点赞举报
我一直执行失败是什么原因
我一直执行失败是什么原因
回复回复点赞举报
推荐阅读
Android自定义控件之滑动解锁
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/149102.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/12
2.1K0
Android自定义控件之滑动解锁
Android滑动解锁功能实现,Android_滑动解锁
图片资源:https://pan.baidu.com/s/1tkcw0tdxV78mnwHqOtcAGg
全栈程序员站长
2022/09/07
1.3K0
一个可以拖动的自定义Gridview代码
这个可以拖动的gridview继承于gridview,所以,用法和gridview一样, 代码如下: public class DragGridView extends GridView { private long dragResponseMS = 700; // item长按响应的时间 private int mDragPosition;// 正在拖拽的position private boolean isDrag = false; // 是否可以拖拽,用于控件内部逻辑实现
xiangzhihong
2018/02/01
1.1K0
10.下拉刷新、加载更多、标记已读、轮播条、缓存
下拉刷新、加载更多、标记已读、轮播条、缓存 下拉刷新------- 1.addHeaderView必须在setAdapter之前调用 2.将paddingTop设置一个headerView高度的负值去隐藏它 getHeight()和getMeasuredHeight()的区别: getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用                    它获取到宽高,在自定义控件内部多使用这个 使用view.measure(0
六月的雨
2018/05/14
1.2K0
可拖拽gridview
在Android开发中,我们常常用到ListView和GridView,而有的时候系统的ListView,GridView并不能满足我们的需求,所以我们需要自己定义一个ListView或者GridView,我的上一篇文章中就是自定义的一个左右滑动删除item的例子,大家有兴趣的可以去看看 Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,今天这篇文章就给大家来自定义GridView的控件,GridView主要是来显示网格的控件,在Android的开发中使用很普通,相对
xiangzhihong
2018/01/29
5.1K0
可拖拽gridview
android滑动监听事件折叠菜单
1.定义两个title布局 2.监听ScrollView控件在下面布局不可见的时候显示第二个title布局
tea9
2022/07/16
2K0
android滑动监听事件折叠菜单
Android 高德地图API(详细步骤+源码)七
在RouteActivity中找到onRideRouteSearched方法,方法里面添加如下代码:
晨曦_LLW
2021/03/04
1.8K4
Android 高德地图API(详细步骤+源码)七
6.下拉刷新
下拉刷新------- 1.addHeaderView必须在setAdapter之前调用 2.将paddingTop设置一个headerView高度的负值去隐藏它 getHeight()和getMeasuredHeight()的区别: getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用                     它获取到宽高,在自定义控件内部多使用这个 使用view.measure(0,0)方法可以主动通知系统去测量,然后就 可
六月的雨
2018/05/14
1.7K0
相关推荐
Android自定义控件之滑动解锁
更多 >
LV.3
这个人很懒,什么都没有留下~
目录
  • nginx 的配置文件
    • /etc/nginx/nginx.conf
    • /etc/nginx/conf.d/default.conf
    • /usr/share/nginx/html
  • 通过 docker 高效学习 nginx 配置
  • root 与 index
  • location
    • location 修饰符验证
    • location 优先级验证
  • proxy_pass
  • add_header
    • Cache
    • CORS
    • HSTS
    • CSP
  • 作业
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档