Table of Contents

  1. 背景
  2. Nginx
    1. Nginx是做什么的
    2. Nginx的常用配置
      1. 安装
      2. 配置文件
  3. 实战踩的坑

背景

机器上现在跑着wordpress 和 frps服务,申请的域名现在是直接到wordpress服务。想着后面做一个个人旅行足迹记录的小web服务,http默认的80和https默认的443端口现在都是给wordpress用着,新的web服务如果使用新的端口,每次在浏览器中输入就是http://www.xxxx.xxx.com:xxx。这样用不同的端口号区别不同服务,不管是用户体验还是实际操作都感觉很不便捷。所以,我们需要到达的是,对外只暴露http/https默认端口,根据二级域名的不同,对内做一个http_proxy转发,转发到相应的服务端口。


Nginx

Nginx是做什么的

之前在百度实习的时候接触过nginx,大概的印象是放在最前端,请求过了后首先碰到的一个组件。当然这是从使用的角度。看了一下手头边上的书–《深入理解Nginx》,上面的定义是:Nginx是一个跨平台的web服务器,具有更快(事件驱动、全异步网络I/O),高扩展性,高可靠性,低内存消耗,单机支持10万以上的并发连接,热部署等特点。对比一下其他的web服务器:

  • Tomcat/Jetty:面向java语言,重量级,性能与nginx没有可比性。
  • IIS:只能在Windows操作系统上运行。Windows作为服务器性能上本来就不如类UNIX操作系统。
  • Lighttpd:轻量级,高性能。
  • Apache:稳定、开源、跨平台,目前领先。重量级、不支持高并发。

    Nginx的常用配置

    安装

    安装
    $ apt-get install nginx
    启动
    $ sudo nginx
    停止
    $ sudo nginx -s stop
    重启
    $ sudo nginx -s reload

    配置文件

    nginx.conf:
    1 #user www-data; #启动nginx woker的用户,默认就可
    2 worker_processes auto;
    3 pid /run/nginx.pid; # nginx pid,stop,relaod会读这个文件
    4 include /etc/nginx/modules-enabled/*.conf;
    5 
    6 events {
    7 worker_connections 768;
    8 # multi_accept on;
    9 }
    10 
    11 http {
    12 
    13 ##
    14 # Basic Settings
    15 ##
    16 
    17 sendfile on;
    18 tcp_nopush on;
    19 tcp_nodelay on;
    20 keepalive_timeout 65;
    21 types_hash_max_size 2048;
    22 # server_tokens off;
    23 
    24 # server_names_hash_bucket_size 64;
    25 # server_name_in_redirect off;
    26 
    27 include /etc/nginx/mime.types;
    28 default_type application/octet-stream;
    29 
    30 ##
    31 # SSL Settings
    32 ##
    33 
    34 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    35 ssl_prefer_server_ciphers on;
    36 
    37 ##
    38 # Logging Settings
    39 ##
    40 
    41 access_log /var/log/nginx/access.log;
    42 error_log /var/log/nginx/error.log;
    43 
    44 ##
    45 # Gzip Settings
    46 ##
    47 
    48 gzip on;
    49 
    50 # gzip_vary on;
    51 # gzip_proxied any;
    52 # gzip_comp_level 6;
    53 # gzip_buffers 16 8k;
    54 # gzip_http_version 1.1;
    55 # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    56 
    57 ##
    58 # Virtual Host Configs
    59 ##
    60 
    61 include /etc/nginx/conf.d/*.conf; #自定义的配置文件可以放这
    62 include /etc/nginx/sites-enabled/*; #自定义的配置文件可以放这
    63 }
    654}
    reverse-proxy.conf:
    1 server {
    2 listen 443 ssl;
    3 server_name winterio.com.cn www.winterio.com.cn;
    4 
    5 ssl on;
    6 ssl_certificate /home/cert/ssl-cert-snakeoil.pem; #pem证书路径
    7 ssl_certificate_key /home/cert/ssl-cert-snakeoil.pem; #pem证书key路径
    8 ssl_session_timeout 5m; #会话超时时间
    9 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #加密算法
    10 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #SSL协议
    11 
    12 access_log /var/log/nginx/reverse-access.log;
    13 error_log /var/log/nginx/reverse-error.log;
    14 location / {
    15 proxy_pass https://127.0.0.1:8080;
    16 }
    17 }
    18 server{
    19 listen 80;
    20 server_name winterio.com.cn www.winterio.com.cn;
    21 location / {
    22 proxy_pass https://127.0.0.1:8080;
    23 }
    24 }
    25 server{
    26 listen 80;
    27 server_name map.winterio.com.cn www.map.winterio.com.cn;
    28 access_log /var/log/nginx/reverse-access.log;
    29 error_log /var/log/nginx/reverse-error.log;
    30 location / {
    31 index /tests/basic.html;
    32 root /home/winter/dev/map/jvectormap;
    33 }
    34 }
    在reverse-proxy.conf文件中,我们定义了两个server项,代表我们后面有两个服务。客户端通过域名访问服务器时会将域名与被解析的ip一同放在请求中。当请求到了nginx中时。nginx会先去匹配ip,如果listen中没有找到对应的ip,就会通过域名进行匹配,匹配成功以后,再匹配端口。当这三步完成,就会找到对应的server的location对应的资源。

实战踩的坑

  1. 既然我们的请求是通过nginx监听443/80端口并进行分发的,那么原来的docker-compose.yaml文件中的端口就要改掉,要不然会产生端口占用的错误。所以wordpress不再直接监听443端口,而是监听8080,reverse-proxy.conf中定义了nginx监听到的https(443)消息,转发给本地的8080(wordpress),本地的8080转发到docker内部的443(wordpress)进行消息的处理。修改后的yaml文件如下:

    1 version: '3.3'
    2 services:
    3 db:
    4 image: mysql:5.7
    5 ports:
    6 - "3306:3306"
    7 # - "443:443"
    8 volumes:
    9 - ./db_data:/var/lib/mysql
    10 restart: always
    11 environment:
    12 MYSQL_ROOT_PASSWORD: somewordpress
    13 MYSQL_DATABASE: wordpress
    14 MYSQL_USER: wordpress
    15 MYSQL_PASSWORD: wordpress
    16 wordpress:
    17 depends_on:
    18 - db
    19 image: wordpress:support_https
    20 ports:
    21 # - "8080:80"
    22 - "8080:443"
    23 restart: always
    24 environment:
    25 WORDPRESS_DB_HOST: db:3306
    26 WORDPRESS_DB_USER: wordpress
    27 WORDPRESS_DB_PASSWORD: wordpress
    28 WORDPRESS_DB_NAME: wordpress
    29 volumes:
    30 - ./html:/var/www/html

    逻辑没有问题,但是一开测试的时候,发现每次使wordpress监听8080端口后,访问不到,即使http://www.winterio.com.cn:8080就会301,rediect到80端口,发现是:
    WordPress在非80端口上时,如果修改了“设置-常规”中的两个URL,那么在访问首页时会被默认重定向到127.0.0.1:80端口。

    解决方法:
    Edit your current theme’s functions.php and add following line after the opening PHP tag to disable canonical redirection.
    remove_filter(‘template_redirect’,’redirect_canonical’); 
    save and exit.

  2. 使nginx打开ssl后,运行nginx会报错:
    [emerg]: SSL_CTX_use_PrivateKey_file(“/home/ssl/xxx.pem”) failed (SSL:
    error:0906D06C:PEM routines:PEM_read_bio:no start line error:140B0009:SSL
    routines:SSL_CTX_use_PrivateKey_file:PEM lib)
    configuration file /etc/nginx/nginx.conf test failed

    原因使要在pem文件中后面加上private-key的内容:

    —–BEGIN CERTIFICATE—–

    —–END CERTIFICATE—–

    —–BEGIN RSA PRIVATE KEY—–

    —–END RSA PRIVATE KEY—–