nginx 在 docker 中的编译与配置见 https://github.com/lanseyujie/docker-lnmp/tree/master/nginx
配置
http://nginx.org/en/docs/ngx_core_module.html
nginx.conf
# 运行的使用的用户和用户组
user nginx nginx;
# 进程数,通常设置成 CPU 的核心数
worker_processes auto;
# 全局错误日志
# 日志级别
# debug info notice warn error crit alert emerg
error_log /var/log/nginx/error.log warn;
# 进程文件,写有当前进程的 pid
pid /var/run/nginx.pid;
# 更改每个进程最大打开文件数
# 可以处理比 ulimit -n 更多的文件而不出现 too many open files
worker_rlimit_nofile 51200;
events {
# 指定 I/O 模型
# epoll 是 Linux kernel 2.6 之后版本中的高性能网络 I/O 模型
# BSD 系列系统应使用 kqueue
use epoll;
# 单个进程最大连接数
worker_connections 51200;
# 默认为禁用,此时一个进程只能同时接受一个新的连接。
# 否则一个进程可以同时接受所有的新连接
# kqueue 模型下会忽略此设置
multi_accept on;
}
http {
# 文件扩展名与文件类型映射表
include /etc/nginx/mime.types;
# 默认的 MIME 类型
default_type application/octet-stream;
# 服务器名称 hash 表大小
server_names_hash_bucket_size 128;
# 为请求头分配一个缓冲区
# 如果请求头大小超过设置值则使用large_client_header_buffers 分配更大的缓冲区
client_header_buffer_size 32k;
# 用于读取大型客户端请求头的缓冲区的最大数量和大小
# 这些缓冲区仅在缺省缓冲区不足时按需分配
# 当处理请求或连接转换到保持活动状态时释放缓冲区
large_client_header_buffers 4 32k;
# 用于设置请求正文的缓冲区大小
# 如果请求正文大小超过设定值且小于 client_max_body_size 则将其写入 client_body_temp 下的临时文件
client_body_buffer_size 10m;
# 客户端请求服务器最大允许大小
# 如果请求头中 Content-Length 的大于此值将抛出 413 错误
client_max_body_size 1024m;
# 启用数据在内核中的文件描述符之间传递,避免数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝
sendfile on;
# 在一个数据包里发送所有头文件,而不一个一个的发送
# 必须与 sendfile 搭配使用
tcp_nopush on;
# 不缓存数据,而是一段一段的发送
tcp_nodelay on;
# 长连接超时时间,单位秒
keepalive_timeout 120;
# 不显示 nginx 版本号
server_tokens off;
# fastcgi 相关
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_intercept_errors on;
# 开启 gzip 压缩
gzip on;
# 压缩缓冲区数量和大小
gzip_buffers 16 8k;
# 压缩级别,级别范围 1-9
gzip_comp_level 6;
# 压缩版本
gzip_http_version 1.1;
# 最小压缩文件大小
gzip_min_length 256;
# 作为反向代理时会根据请求头中的 Via 字段判断是否压缩
# expired 当请求头中包含 Expires 头信息时启用压缩
# no-cache 当请求头中包含 Cache-Control:no-cache 头信息时启用压缩
# no-store 当请求头中包含 Cache-Control:no-store 头信息时启用压缩
# private 当请求头中包含 Cache-Control:private 头信息时启用压缩
# no_last_modified 当请求头中不包含 Last-Modified 头信息时启用压缩
# no_etag 当请求头中不包含 ETag 头信息时启用压缩
# auth 当请求头中包含 Authorization 头信息时启用压缩
# any 无条件启用压缩
# off 不启用压缩
gzip_proxied any;
# 开启后会在响应头添加 Accept-Encoding:gzip
gzip_vary on;
# 除 html 外需要压缩的 MIME 类型
gzip_types
text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
text/javascript application/javascript application/x-javascript
text/x-json application/json application/x-web-app-manifest+json
text/css text/plain text/x-component
font/opentype application/x-font-ttf application/vnd.ms-fontobject
image/x-icon;
# 对 IE 6 及以下浏览器不使用压缩
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# 如果作为静态文件服务器,缓存文件的元数据而不是实际文件的内容会节省一些延迟
# max 设置最大缓存元素数,超出后使用 LRU 算法删除元素
# inactive 如果未设定时间内访问该元素则从缓存中删除,默认为 60s
# off 禁用缓存
# open_file_cache max=1000 inactive=20s;
# 缓存元素有效期,超过有效期将会重新检查元信息
# open_file_cache_valid 30s;
# inactive 时间内文件最少使用次数,超过次数将继续标记元素为活动使用,否则将被从缓存中删除
# open_file_cache_min_uses 2;
# 启用则缓存文件查找时的错误,而不再查找资源
# open_file_cache_errors on;
include /etc/nginx/conf.d/http/*.conf;
}
stream {
# include /etc/nginx/conf.d/stream/*.conf;
}虚拟主机配置
常规配置
server {
listen 80;
# listen 443 ssl http2;
server_name localhost;
# ssl_certificate /etc/nginx/ssl/fullchain.cer;
# ssl_certificate_key /etc/nginx/ssl/cert.key;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
# ssl_prefer_server_ciphers on;
# ssl_buffer_size 1400;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 10m;
# ssl_session_tickets on;
# note: openssl rand 48 > /etc/nginx/ssl/session_ticket.key
# ssl_session_ticket_key /etc/nginx/ssl/session_ticket.key;
# note: openssl s_client -connect example.com:443 -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
# ssl_stapling on;
# ssl_stapling_verify on;
# ssl_trusted_certificate /etc/nginx/ssl/fullchain.cer;
# resolver 8.8.4.4 8.8.8.8 valid=300s;
# resolver_timeout 10s;
# note: openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
# ssl_dhparam /etc/nginx/ssl/dhparam.pem;
charset utf-8;
access_log /var/log/nginx/access.log combined;
root /data/default;
index index.html index.htm index.php;
# if ($ssl_protocol = "") {
# return 301 https://$host$request_uri;
# }
# error_page 404 /404.html;
# error_page 500 /500.html;
# error_page 502 /502.html;
# error_page 504 /504.html;
# note: HSTS (15768000 seconds = 6 months)
# add_header Strict-Transport-Security "max-age=15768001; preload";
# add_header Cache-Control "no-cache, must-revalidate, max-age=60";
# add_header X-Content-Type-Options nosniff;
# add_header X-Frame-Options SAMEORIGIN;
# add_header Content-Security-Policy "default-src 'self'; script-src 'unsafe-inline':; style-src 'unsafe-inline'; img-src data:; media-src *;"
# fastcgi_hide_header X-Powered-By;
# location / {
# try_files $uri $uri/ /index.php$is_args$args;
# }
# location / {
# autoindex on;
# autoindex_exact_size off;
# autoindex_localtime on;
# }
# location / {
# proxy_connect_timeout 20;
# proxy_read_timeout 30;
# proxy_send_timeout 30;
# send_timeout 30;
# proxy_redirect off;
# 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_pass http://127.0.0.1:8080;
# proxy_intercept_errors on;
# }
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
# location ~ [^/]\.php(/|$) {
# note: comment here if you use path info
# try_files $uri =404;
# fastcgi_pass php:9000;
# fastcgi_index index.php;
# include /etc/nginx/fastcgi.conf;
# }
location ~ .*\.(gif|jpg|jpeg|png|webp|bmp|ico|svg|mp3|mp4|mkv)$ {
# valid_referers none blocked server_names ~\.google\. ~\.baidu\.;
# if ($invalid_referer) {
# return 403;
# # rewrite ^/ http://domain/forbidden.png;
# }
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 30d;
access_log off;
}
location ~.*.mp4$ {
mp4;
}
# location /download {
# internal;
# # alias /data/download;
# secure_link $arg_token,$arg_expires;
# secure_link_md5 "$secure_link_expires$uri$remote_addr mySecret";
# if ($secure_link = "") { return 403; }
# if ($secure_link = "0") { return 410; }
# }
location ~ /\. {
deny all;
}
}禁止使用IP访问
server {
listen 80 default;
# listen 443 ssl default;
server_name _;
# note: openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/default.key -out /etc/nginx/ssl/default.cer
# ssl_certificate /etc/nginx/ssl/default.cer;
# ssl_certificate_key /etc/nginx/ssl/default.key;
return 444;
}负载均衡
upstream backend {
hash $remote_addr consistent;
server 192.168.1.2:9000;
server 192.168.1.3:9000;
server 192.168.1.4:9000;
server 192.168.1.5:9000;
}
server {
listen 9000;
proxy_connect_timeout 5s;
proxy_timeout 30s;
proxy_pass backend;
}变量
http://nginx.org/en/docs/http/ngx_http_core_module.html
# nginx 所在主机的主机名 $hostname # nginx 版本号 $nginx_version # 进程号 $pid # 当前的时间,毫秒 $msec # 请求的主机,如 lanseyujie.com 或 10.0.0.2 $host # 当前请求的 root 或 alias 指令的值 $document_root # 与当前请求的 root 或 alias 指令的值相对应的绝对路径名 # 所有符号链接都解析为真实路径 $realpath_root # 接受请求的服务器名称 $server_name # 接受请求的服务器地址 $server_addr # 接受请求的服务器端口 $server_port # 协议版本,如 HTTP/1.1 $server_protocol # 请求协议,如 https $scheme # 如果使用了 ssl 则为 on,否则为空 $https # PROXY 协议头中的客户端地址 # 必须通过在 listen 指令中设置 proxy_protocol 参数来预先启用 PROXY 协议 $proxy_protocol_addr # PROXY 协议头中的服务器地址 $proxy_protocol_server_addr # PROXY 协议头中的服务器端口 $proxy_protocol_server_port # 客户端地址 $remote_addr # 客户端端口 $remote_port # Basic Auth 验证的用户名 $remote_user # 请求速率限制 $limit_rate # 完整的原始请求行 $request # 获取一个请求头字段 # 字段名称为小写字母,并用 _ 代替 - $http_[header] # 请求方式,如 POST $request_method # 请求头中的 Content-Length 字段 $content_length # 请求头中的 Content-Type 字段 $content_type # 获取 cookie 中的一个字段值 $cookie_[name] # 请求中带有 GET 参数其值为 ?,无则为空 $is_args # GET 请求参数,如 id=2&type=3 $args # 获取一个 GET 参数的值 # 如请求参数为 id=2&type=3,则 $arg_id 为 2 $arg_[parameter] # 同 $args $query_string # 生成 16 位十六进制随机字节的唯一请求标识符 $request_id # 原始 URI,如 /member/profile?id=1&type=2 $request_uri # 不带参数的 URI,如 /member/profile # 可能会在请求处理期间更改,例如在进行内部重定向或使用索引文件时 $uri # 同 $uri $document_uri # 请求正文 # 当请求正文被读到内存缓冲区时,该变量在 proxy_pass,fastcgi_pass,uwsgi_pass和scgi_pass 指令中可用 $request_body # 带有请求正文的临时文件的名称 $request_body_file # 当前请求的文件路径 # 由 root 或 alias 和 URI 构成 $request_filename # 从客户端读取第一个字节以来经过的时间,单位:毫秒 $request_time # 发送给客户端的字节数 $bytes_sent # 发送给客户端的字节数,不计算响应头 $body_bytes_send # 获取一个响应头字段 # 字段名称为小写字母,并用 _ 代替 - $sent_http_[header] # 在响应末尾发送的任意字段 # 字段名称为小写字母,并用 _ 代替 - $sent_trailer_[header] # 响应状态 $status # 如果请求已完成则为 OK,否则为空 $request_completion
语法
location [ = | ~ | ~* | ^~ ] uri {
...
}匹配类型
没有修饰符时,为前缀匹配,将匹配 URI 开头部分与规则相同的请求。
修饰符为 = 时,为精准匹配,若匹配到与规则完全一致的 URI,就停止查找并使用该 location。
修饰符为 ~ 时,为大小写敏感的正则匹配。
修饰符为 ~* 时,为大小写不敏感的正则匹配。
修饰符为 ^~ 时,非正则匹配,正则表达式无效。
匹配顺序
首先查找前缀匹配,为每个前缀匹配都匹配一遍,暂存这个 location 。
再查找精准匹配,如果匹配上就停止查找并使用该 location。
如果精准匹配没有匹配上,会按照如下步骤继续查找最长前缀匹配:如果最长前缀匹配有 ^~ 修饰符,会停止查找并使用该 location;如果没有使用 ^~ 修饰符,暂存这个 location 并且继续查找。
若有最长前缀匹配被暂存,会再查找是否有使用 ~ 或 ~* 修饰且符合规则的 location,若有将使用第一个匹配上 location,若没有则使用前面暂存的 location。
其他语法
set variable value:设置变量。
if (condition) {}:-f 检测文件存在;-d 检测路径存在;-e 检测文件、路径或符号连接存在;-x 检测可执行文件存在。
return code:结束规则执行并返回状态码。使用如 444 等非标准状态码可以不发送任何响应头来结束连接。
rewrite regexp replacement flag:重定向 URI,重写的表达式只对相对路径有效。
rewrite 中几种 flag 的释义:
break:停止 rewrite 检测,该句为 rewrite 的最终结果,不再进行 location 匹配。
last:停止 rewrite 检测,last 语句不一定是最终结果,要进行 location 匹配,重定向到相同的规则会导致死循环。
permanent:301 永久重定向到新 URL。
redirect:302 临时重定向到新 URL。