静态资源托管、动态资源反向代理+负载均衡……Docker+Nginx如何搭配使用?
Nginx 是一个流行的服务器。常用于反向静态资源和代理动态资源。
Docker 是一种流行的容器技术,可以运行任何服务。
如何结合使用Docker和Nginx?
我们来试试:
首先下载Docker,直接安装Docker Desktop:
用于管理容器和镜像:
安装完成后,❀可用。让我们运行 nginx 镜像。
搜索nginx(这一步需要科学上网,因为需要访问hub.doccker.com),点击运行:
输入容器名称和要映射的端口:
这里映射主机机器到端口80的容器中的端口81,单击运行。
现在可以看到docker容器正在运行,并且打印了日志:
用浏览器访问http://localhost:81,你会看到nginx的欢迎页面:
很明显是在容器启动服务。
但是当前页面是默认的。我想使用 nginx 来托管一些静态 html 页面。我应该怎么办?
首先我们需要知道当前的配置文件和页面在哪里。
在文件面板中可以看到容器内的文件:
/usr/share/nginx/html/ 文件夹包含所有静态文件。
双击打开index.html文件,可以看到:
这正是我们在浏览器中看到的。
也就是说,这个目录就是存放静态文件的目录。
我们可以将 html 放在该目录中吗?
我们先复制这个目录:
bash复制代码
docker cp nginx1:/usr/share/nginx/html ~/nginx-html
docker cp 该命令用于在主机和容器之间复制文件和目录。
比如我们把这个目录复制到容器中:
docker cp ~/nginx-html nginx1:/usr/share/nginx/html-xxx
可以看到容器里有这个目录:
然后我们在这个目录下添加两个html试试:
echo aaa > aaa.html
echo bbb > bbb.html
docker cp ~/nginx-html nginx1:/usr/share/nginx/html
if 如果目标目录存在,docker会将其复制到目标目录:
我们需要先删除然后复制容器目录:
docker cp ~/nginx-html nginx1:/usr/share/nginx/html
没问题:
然后尝试用浏览器访问它:
现在你可以访问容器内的这些目录。
即只要放置在 /usr/share/nginx/html 下的文件是可以访问的。
但是为什么呢?
这是因为默认的 nginx 配置。
我们看一下nginx的配置文件,它是/etc/nginx/nginx.conf。
复制下来看看:
docker cp nginx1:/etc/nginx/nginx.conf ~/nginx-html
这是nginx默认的配置:
其实叫nginx.conf作为主配置文件,一般包含一些全局设置,比如目录错误日志等。
可以看到包含了http all,引入了/etc/nginx/conf.d/*.conf文件的配置。
一般情况下,具体的路由配置都在这些子配置文件中。
目录conf.d表示配置目录。
我们复制这个目录看看:
docker cp nginx1:/etc/nginx/conf.d ~/nginx-html
所有的localhost:80虚拟主机路由都配置在这里。
什么是虚拟主机?
您可以使用单个nginx服务器为多个域名和端口提供服务。
只需添加更多服务器配置即可。
这里我们配置虚拟主机localhost:80。
下面的位置是路由配置。
例如这样的配置:
这会配置/下的所有路由,并在root用户指定的目录中查找它们。
所以 http://localhost/aaa.html 可以在 /usr/share/nginx/html/aaa.html 中找到。
位置支持多种语法。让我们试试这些:
location = /111/ {
default_type text/plain;
return 200 "111 success";
}
location /222 {
default_type text/plain;
return 200 $uri;
}
location ~ ^/333/bbb.*\.html$ {
default_type text/plain;
return 200 $uri;
}
location ~* ^/444/AAA.*\.html$ {
default_type text/plain;
return 200 $uri;
}
删除之前的位置/并添加这些路由配置。
这些配置的具体含义稍后讨论。
将此文件复制到容器:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
然后在容器内的终端中运行它:
nginx -s reload
重新加载配置文件。
然后看第一条路由:
在location和path之间添加=表示精确匹配,即只有完全相同的URL才匹配此路由。
Without = 表示基于前缀后跟任何路径的匹配。
$这里是选择当前曲目。
如果想支持正则表达式可以加~。
这里正常的语法并不难理解,以/aaaa/bbb开头,然后中间有随机字符,最后url以.html结尾。
但区分大小写。例如,这不起作用:
只需将其更改为小写:
如果您希望正则表达式不区分大小写,您可以添加*
并尝试:
任何大写或小写信是可以接受的。
另外,还有一种语法:
将此配置添加到配置文件中:
location /444 {
default_type text/plain;
return 200 'xxxx';
}
然后复制到容器中并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
目前有两条 /444 路由:
目前,浏览器访问还是匹配上面的路线:
如果想提高优先级,可以使用^~
,改成:
location ^~ /444 {
default_type text/plain;
return 200 'xxxx';
}
然后复制到容器中重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
这个如果匹配相同的 URL,会匹配如下路由:
也就是说,^~ 可以提高前缀匹配优先级。
综上所述,一共有 4 种位置语法:
location = /aaa 是与 /aaa 完全匹配的路线。
位置 /bbb 是前缀为 /bbb 的路由。
location ~ /ccc.*.html 是常见匹配。您可以添加 * 来指示区分大小写的位置 ~* /ccc.*.html
位置 ^~ /ddd 是等效的前缀,但具有更高的优先级。
这四种语法的优先级如下:
精确匹配(=)>高优先级前缀匹配(^~)>普通匹配(~~*)>普通前缀匹配
我们现在正在返回内容直接使用 return 实际上应该返回一个 html 文件。
可以这样改:
location /222 {
alias /usr/share/nginx/html;
}
location ~ ^/333/bbb.*\.html$ {
alias /usr/share/nginx/html/bbb.html;
}
然后复制到容器中,重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
大家可以正确返回对应的html:
我之前用过root:
root 和 root 有什么区别别名? ?
例如以下两个配置:
location /222 {
alias /dddd;
}
location /222 {
root /dddd;
}
也是/222/xxx/yyy.html。如果使用根配置,则整个 uri 将合并为路径。
这意味着它正在寻找/dddd/222/xxx/yyy.html。
如果这是别名配置,它将在删除/222后连接部分路径。
这意味着它正在寻找 /dddd/xxx/yyy.html。
这意味着我们的根和别名的区别在于拼接路径时是否包含条件路径。
这是nginx的第一个特性:静态文件托管。
主配置文件位于/etc/nginx/nginx.conf目录,子配置文件位于/etc/nginx/conf.d目录。
HTML 的默认路径是 /usr/share/nginx/html。
然后我们来看看nginx的另一个主要功能:动态资源的反向代理。
什么是正向,什么是反向?
从用户的角度来看,方向为正向,反向为相反方向。
例如,有两个这样的代理:
第一个是正向代理,第二个是反向代理。
第一个代理是代理用户的请求,与用户的请求同向,称为转发。
另一种代理服务器是与用户请求相反方向处理用户请求的代理服务器。这称为反向代理。
在测试 nginx 作为反向代理之前,我们首先创建一个套接字服务。
npx nest new nest-app -p npm
启动服务:
npm run start:dev
使用浏览器访问http://localhost:3000。如果看到hello world,则说明socket服务已成功运行:
添加全局前缀/api
更改为nginx 配置并添加路由:
location ^~ /api {
proxy_pass http://192.168.1.6:3000;
}
该路由匹配以/api前缀开头的URL。 ^~ 用于提高优先级。
然后复制到容器中并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
然后访问http://localhost:81/api,看到socket服务返回的响应:
也就是说是这样的:
为什么我们需要更多的 nginx 代理吗?
当然,在这个关卡你可以做很多事情。
例如,更改标头:
,然后将其复制到容器并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
将标头放入套接字服务处理程序中,打印它:
,然后使用此按钮打开浏览器。
如果直接访问socket服务,则没有这样的头:
访问nginx反向代理并进行传输:
这是一个反向代理角色,可以透明地修改请求和响应。
另外,你还可以用它来进行负载均衡。
在控制器中打印访问日志:
停止套接字服务,然后重新启动 npm run start
为 3001 和 3002 运行一个端口:
如果浏览器使用正常访问:
控制台还打印访问日志:
问题来了。现在有一台nginx服务器和两台socket服务器。 nginx 应该如何反应?
nginx的解决方案是负载均衡,将请求按照一定的规则分发到不同的服务器上。
编辑 nginx 配置文件:
配置上游与代理一起使用的所有目标服务器实例。
下面的 proxy_pass 由上游名称指定。
然后复制到容器并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
现在我访问 http://localhost:81/api 并刷新页面 5 次:
我看到两个套接字服务,一个 3 次,一个 2 次。第二名。
因为默认是poll。
负载均衡策略一共有4种:
- 轮询:默认方式。
- weight:根据poll添加权重,即poll概率不同。
- ip_hash:根据IP哈希分布,保证每个访问者的请求安全访问服务器,解决会话问题。
- 诚实:按照响应时间分配。这需要安装 nginx-upstream-fair 插件。
我们来测试一下weight和ip_hash方法。
添加权重=2,默认为1,所以两台服务器询问你的几率是2:1。
然后复制到容器中并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
按command + k删除socket服务控制台日志:
然后访问http://localhost:81/api
查看打印的日志,这几乎是 2:1 的投票概率。
这是一项加权民意调查。
我们再尝试一下ip_hash方法;
然后复制到容器中并重新加载:
docker cp ~/nginx-html/conf.d/default.conf nginx1:/etc/nginx/conf.d/default.conf
按 command + k 清除 Nest 服务控制台日志:
重新访问 http://localhost:81/api
可以看到请求已已发送到服务器:
这是Nginx的负载均衡策略。
总结
我们通过docker运行nginx服务器,并使用其静态资源托管功能和动态资源的反向代理功能。
nginx配置文件位于/etc/nginx/nginx.conf,默认还引入了/etc/nginx/conf.d下的子配置文件。
默认情况下,html 放置在 /usr/share/nginx/html 下。
我们可以使用docker cp将容器中的文件复制到主机上进行修改。
更改nginx配置,在服务器上配置路由,根据不同的URL返回不同的静态文件。
location 语法有 4 种:
- location /aaa 前缀
- location 匹配 ~^ /aaa 前缀匹配,优先级较高
- location 匹配 /aaa /.*html 正常匹配
- location ~ * /aaa/.*html 正常匹配且区分大小写
优先级为精确匹配(=) > 高优先级前缀匹配(^~) > 正常匹配(~ ~*) > 普通前缀匹配
除了静态资源托管,nginx还可以对动态资源做反向代理。
这意味着请求被发送到nginx,nginx将其转发到应用服务器。该层也可称为栅极。
nginx反向代理可以修改请求和响应信息,例如设置标头。
如果有多个应用服务器,可以在上游配置负载均衡。有 4 种策略:poll、weighted poll、ip_hash 和 fair。
一旦掌握了静态资源托管和动态资源反向代理+负载均衡,你就掌握了Nginx的基本使用。作者:zxg_上帝说一定有光
来源:稀土矿块
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网