• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    为docker中的nginx配置https的方法步骤

    没有 https 加持的网站会逐渐地被浏览器标记为不安全的,所以为网站添加 https 已经变得刻不容缓。对于商业网站来说,花钱购买 SSL/TLS 证书并不是什么问题。但对于个人用户来说,如果能有免费的 SSL/TLS 证书可用将会是非常幸福的事情!Let's Encrypt 就是一个提供免费 SSL/TLS 证书的网站,由于其证书期限只有三个月,所以需要我们用自动化的方式去更新证书。本文将介绍如何为通过 docker 运行的 nginx 中的站点添加 https 支持,并自动完成证书的更新。本文的演示环境为:运行在 Azure 上的 Ubuntu 16.04 主机(此图来自互联网):

    准备环境

    在 Azure 上创建 Ubuntu 类型的虚机事件非常容易的事情,安装 docker 也无须赘言。比较容易忽略的是配置合适的网络安全组规则,比如打开 80 和 443 端口:

    还有就是配置 DNS:

    创建一个普通的 http 站点

    简单起见,直接使用一个镜像中的 nodejs 应用作为 web 站点:

    $ docker pull ljfpower/nodedemo
    $ docker network create -d bridge webnet
    $ docker run -d --restart=always --expose=3000 \
    
       --network=webnet --name=myweb \
    
       ljfpower/nodedemo

    在用户的家目录下创建 nginx 目录及其子目录 conf.d、conf.crt 和 html,创建 logs 目录及其子目录 nginx 和 letsencrypt:

    $ mkdir -p nginx/{conf.d,conf.crt,html}
    $ mkdir -p logs/{nginx,letsencrypt}

    说明,本文演示的示例中需要我们手动创建的文件和目录结构如下:

    创建 nginx/nginx.conf 文件,内容如下:

    user nginx;
    worker_processes auto;
    
    error_log /var/log/nginx/error.log warn;
    pid  /var/run/nginx.pid;
    
    events {
     worker_connections 2048;
    }
    
    http {
     include  /etc/nginx/mime.types;
     default_type application/octet-stream;
    
     sendfile  on;
     keepalive_timeout 65;
     client_max_body_size 10M;
    
     include /etc/nginx/conf.d/*.conf;
    }

    然后创建 nginx/conf.d/default.conf 文件,内容如下:

    upstream web{
     server myweb:3000;
    }
    server {
     listen  80;
     listen  [::]:80;
     server_name filterinto.com www.filterinto.com;
    
     location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /usr/share/nginx/html;
     }
     location = /.well-known/acme-challenge/ {
      return 404;
     }
     location / {
      proxy_pass http://web;
     }
    }

    其中 /.well-known/acme-challenge/ 目录是 certbot 工具在生成证书时创建的。接下来创建文件 nginx/html/index.html 文件,内容如下:

    <!DOCTYPE html>
    <html>
    <head>
     <meta charset="utf-8" />
     <title>Let's Encrypt First Time Cert Issue Site</title>
    </head>
    <body>
     <h1>Hello HTTPS!</h1>
     <p>
      Just used for the very first time SSL certificates are issued by Let's Encrypt's
      certbot.
     </p>
    </body>
    </html>

    这个页面也是 certbot 在生成证书时需要用到的。最后让我们启动容器(在用户的家目录下执行下面的命令):

    $ docker run -d \
    
     -p 80:80 \
    
     -v $(pwd)/nginx/conf.d:/etc/nginx/conf.d:ro \
    
     -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
    
     -v $(pwd)/logs/nginx:/var/log/nginx \
    
     -v $(pwd)/nginx/html:/usr/share/nginx/html \
    
     --restart=always \
    
     --name=gateway \
    
     --network=webnet \
    
     nginx:1.14

    注意:这时没有映射 443 端口,也没有挂载存放证书的目录。只能以 http 协议访问访问我们的站点:

    为站点生成 SSL/TLS 证书

    Let's Encrypt 是一个提供免费 SSL/TLS 证书的网站,它为用户提供了 certbot 工具用来生成 SSL/TLS 证书。方便起见,我们把 certbot 简单的封装到容器中。在用户的家目录下创建 certbot 目录,进入 certbot 目录并把下面的内容保存到 Dockerfile 文件中:

    FROM alpine:3.4
    RUN apk add --update bash certbot
    VOLUME ["/etc/letsencrypt"]

    然后执行下面的命令创建 certbot 镜像:

    $ docker build -t certbot:1.0 .

    然后在 certbot 目录下创建自动更新证书的脚本 renew_cert.sh,内容如下:

    #!/bin/bash
    WEBDIR="$1"
    LIST=('filterinto.com' 'www.filterinto.com')
    LED_LIST=()
    WWW_ROOT=/usr/share/nginx/html
    for domain in ${LIST[@]};do
     docker run \
    
      --rm \
    
      -v ${WEBDIR}/nginx/conf.crt:/etc/letsencrypt \
    
      -v ${WEBDIR}/logs/letsencrypt:/var/log/letsencrypt \
    
      -v ${WEBDIR}/nginx/html:${WWW_ROOT} \
    
      certbot:1.0 \
    
      certbot certonly --verbose --noninteractive --quiet --agree-tos \
    
      --webroot -w ${WWW_ROOT} \
    
      --email="nick.li@grapecity.com" \
    
      -d "$domain"
     CODE=$?
     if [ $CODE -ne 0 ]; then
      FAILED_LIST+=($domain)
     fi
    done
    
    # output failed domains
    if [ ${#FAILED_LIST[@]} -ne 0 ];then
     echo 'failed domain:'
     for (( i=0; i<${#FAILED_LIST[@]}; i++ ));
     do
      echo ${FAILED_LIST[$i]}
     done
    fi

    在用户的家目录中执行 ./renew_cert.sh /home/nick 命令就可以生成新的证书(/home/nick 为当前用户的家目录)。生成的证书被保存在 /home/nick/nginx/conf.crt/live 目录下,以域名命名的目录下保存着该域名的证书:

    然后去检查下 nginx/html 目录,发现多了一个隐藏的 .well-known 目录,这个目录就是在生成证书时创建的:

    有了 SSL/TLS 证书,接下来我们就可以配置 https 站点了。

    为站点配置 SSL/TLS 证书

    有了 SSL/TLS 证书,接下来更新 nginx 的配置文件就可以了,更新 nginx/conf.d/default.conf 的内容如下:

    upstream web{
     server myweb:3000;
    }
    
    server {
     listen  80;
     listen  [::]:80;
     server_name filterinto.com www.filterinto.com;
    
     location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /usr/share/nginx/html;
     }
     location = /.well-known/acme-challenge/ {
      return 404;
     }
     return 301 https://$server_name$request_uri;
    }
    server {
     listen  443;
     listen  [::]:443;
     server_name filterinto.com;
    
     # enable ssl
     ssl      on;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     ssl_ciphers    "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    
     # config ssl certificate
     ssl_certificate   conf.crt/live/filterinto.com/fullchain.pem;
     ssl_certificate_key  conf.crt/live/filterinto.com/privkey.pem;
    
     location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /usr/share/nginx/html;
     }
     location = /.well-known/acme-challenge/ {
       return 404;
     }
     location / {
      proxy_pass http://web;
     }
    }
    server {
     listen  443;
     listen  [::]:443;
     server_name www.filterinto.com;
    
     # enable ssl
     ssl      on;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     ssl_ciphers    "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    
     # config ssl certificate
     ssl_certificate   conf.crt/live/www.filterinto.com/fullchain.pem;
     ssl_certificate_key  conf.crt/live/www.filterinto.com/privkey.pem;
    
     location ^~ /.well-known/acme-challenge/ {
      default_type "text/plain";
      root /usr/share/nginx/html;
     }
     location = /.well-known/acme-challenge/ {
       return 404;
     }
     location / {
      proxy_pass http://web;
     }
    }

    然后删除容器 gateway 并用下面的脚本重新创建:

    $ docker run -d \
    
     -p 80:80 \
    
     -p 443:443 \
    
     -v $(pwd)/nginx/conf.d:/etc/nginx/conf.d:ro \
    
     -v $(pwd)/nginx/conf.crt:/etc/nginx/conf.crt:ro \
    
     -v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
    
     -v $(pwd)/logs/nginx:/var/log/nginx \
    
     -v $(pwd)/nginx/html:/usr/share/nginx/html \
    
     --restart=always \
    
     --name=gateway \
    
     --network=webnet \
    
     nginx:1.14

    现在就只能通过 https 来访问站点了:

    自动更新证书

    Let's Encrypt 提供的 SSL/TLS 证书期限只有三个月,每过三个月要手动更新一次证书也够呛的,下面我们介绍自动更新证书的方法。

    其实我们的配置已经为自动化更新证书提供了最大的便利(其实是使用 docker 带来的便利),在定时任务中添加下面两条记录就可以了:

    0 0 1 * * /home/nick/certbot/renew_cert.sh /home/nick >> /home/nick/logs/cert.log 2>> /home/nick/logs/cert.error.log
    0 1 1 * * docker exec gateway nginx -s reload

    每月 1 号的 0 点更新证书,一个小时后 reload nginx 的配置。

    总结

    Let's Encrypt 是一个非常棒的网站,对于初学者和个人来说,能够帮助我们轻松的实现 HTTPS 站点(还是免费的)!在方便的同时,其隐患也是显而易见的:既然谁都可以无门槛的获得 SSL/TLS 证书,那么非法网站也可以通过它把自己伪装成看上去合法的站点。 所以千万不要片面的认为 HTTPS 站点就是安全的!

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    上一篇:docker安装nginx并配置通过https访问的方法
    下一篇:Docker中运行nginx并挂载本地目录到镜像中的方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    为docker中的nginx配置https的方法步骤 为,docker,中的,nginx,配置,