侠客行小李 發表於 2018-6-11 08:31:00

为 docker 中的 nginx 配置 https

<p><span style="font-family: Microsoft YaHei; font-size: 15px">没有 https 加持的网站会逐渐地被浏览器标记为不安全的,所以为网站添加 https 已经变得刻不容缓。对于商业网站来说,花钱购买 SSL/TLS 证书并不是什么问题。但对于个人用户来说,如果能有免费的 SSL/TLS 证书可用将会是非常幸福的事情!Let's Encrypt 就是一个提供免费 SSL/TLS 证书的网站,由于其证书期限只有三个月,所以需要我们用自动化的方式去更新证书。本文将介绍如何为通过 docker 运行的 nginx 中的站点添加 https 支持,并自动完成证书的更新。本文的演示环境为:运行在 Azure 上的 Ubuntu 16.04 主机(此图来自互联网):</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135139941-1961405780.png"></span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">准备环境</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在 Azure 上创建 Ubuntu 类型的虚机事件非常容易的事情,安装 docker 也无须赘言。比较容易忽略的是配置合适的网络安全组规则,比如打开 80 和 443 端口:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135237569-74306838.png"></span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">还有就是配置 DNS:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135257459-1986926436.png"></span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">创建一个普通的 http 站点</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">简单起见,直接使用一个镜像中的 nodejs 应用作为 web 站点:</span></p>
<div class="cnblogs_code">
<pre>$ docker pull ljfpower/<span style="color: rgba(0, 0, 0, 1)">nodedemo
$ docker network create </span>-<span style="color: rgba(0, 0, 0, 1)">d bridge webnet
$ docker run </span>-d --restart=always --expose=<span style="color: rgba(128, 0, 128, 1)">3000</span><span style="color: rgba(0, 0, 0, 1)"> \
         </span>--network=webnet --name=<span style="color: rgba(0, 0, 0, 1)">myweb \
         ljfpower</span>/nodedemo</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在用户的家目录下创建 nginx 目录及其子目录 conf.d、conf.crt 和 html,创建 logs 目录及其子目录 nginx 和 letsencrypt:</span></p>
<div class="cnblogs_code">
<pre>$ <span style="color: rgba(0, 0, 255, 1)">mkdir</span> -p nginx/<span style="color: rgba(0, 0, 0, 1)">{conf.d,conf.crt,html}
$ </span><span style="color: rgba(0, 0, 255, 1)">mkdir</span> -p logs/{nginx,letsencrypt}</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">说明,本文演示的示例中需要我们手动创建的文件和目录结构如下:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610144437947-689862740.png"></span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">创建 nginx/nginx.conf 文件,内容如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">usernginx;
worker_processesauto;

error_log</span>/var/log/nginx/<span style="color: rgba(0, 0, 0, 1)">error.log warn;
pid      </span>/var/run/<span style="color: rgba(0, 0, 0, 1)">nginx.pid;

events {
    worker_connections</span><span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">;
}

http {
    include       </span>/etc/nginx/<span style="color: rgba(0, 0, 0, 1)">mime.types;
    default_typeapplication</span>/octet-<span style="color: rgba(0, 0, 0, 1)">stream;

    sendfile      on;
    keepalive_timeout    </span><span style="color: rgba(128, 0, 128, 1)">65</span><span style="color: rgba(0, 0, 0, 1)">;
    client_max_body_size 10M;

    include </span>/etc/nginx/conf.d<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">.conf;
}</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">然后创建 nginx/conf.d/default.conf 文件,内容如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">upstream web{
    server myweb:</span><span style="color: rgba(128, 0, 128, 1)">3000</span><span style="color: rgba(0, 0, 0, 1)">;
}
server {
    listen      </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)">;
    listen      [::]:</span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)">;
    server_name filterinto.com www.filterinto.com;

    location </span>^~ /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      default_type </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/plain</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      root </span>/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html;
    }
    location </span>= /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      return </span><span style="color: rgba(128, 0, 128, 1)">404</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    location </span>/<span style="color: rgba(0, 0, 0, 1)"> {
      proxy_pass http:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">web;</span>
<span style="color: rgba(0, 0, 0, 1)">    }
}</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">其中 /.well-known/acme-challenge/ 目录是 certbot 工具在生成证书时创建的。接下来创建文件 nginx/html/index.html 文件,内容如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;!</span><span style="color: rgba(255, 0, 255, 1)">DOCTYPE html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">meta </span><span style="color: rgba(255, 0, 0, 1)">charset</span><span style="color: rgba(0, 0, 255, 1)">="utf-8"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Let's Encrypt First Time Cert Issue Site<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Hello HTTPS!<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">p</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
      Just used for the very first time SSL certificates are issued by Let's Encrypt's
      certbot.
    </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">p</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">这个页面也是 certbot 在生成证书时需要用到的。最后让我们启动容器(在用户的家目录下执行下面的命令):</span></p>
<div class="cnblogs_code">
<pre>$ docker run -<span style="color: rgba(0, 0, 0, 1)">d \
    </span>-p <span style="color: rgba(128, 0, 128, 1)">80</span>:<span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)"> \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/conf.d:/etc/nginx/<span style="color: rgba(0, 0, 0, 1)">conf.d:ro \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/nginx.conf:/etc/nginx/<span style="color: rgba(0, 0, 0, 1)">nginx.conf:ro \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/logs/nginx:/var/log/<span style="color: rgba(0, 0, 0, 1)">nginx \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/html:/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html \
    </span>--restart=<span style="color: rgba(0, 0, 0, 1)">always \
    </span>--name=<span style="color: rgba(0, 0, 0, 1)">gateway \
    </span>--network=<span style="color: rgba(0, 0, 0, 1)">webnet \
    nginx:</span><span style="color: rgba(128, 0, 128, 1)">1.14</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">注意:这时没有映射 443 端口,也没有挂载存放证书的目录。只能以 http 协议访问访问我们的站点:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135531192-395149665.png"></span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">为站点生成 SSL/TLS 证书</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">Let's Encrypt 是一个提供免费 SSL/TLS 证书的网站,它为用户提供了 certbot 工具用来生成 SSL/TLS 证书。方便起见,我们把 certbot 简单的封装到容器中。在用户的家目录下创建 certbot 目录,进入 certbot 目录并把下面的内容保存到 Dockerfile 文件中:</span></p>
<div class="cnblogs_code">
<pre>FROM alpine:<span style="color: rgba(128, 0, 128, 1)">3.4</span><span style="color: rgba(0, 0, 0, 1)">
RUN apk add </span>--<span style="color: rgba(0, 0, 0, 1)">update bash certbot
VOLUME [</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/etc/letsencrypt</span><span style="color: rgba(128, 0, 0, 1)">"</span>]</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">然后执行下面的命令创建 certbot 镜像:</span></p>
<div class="cnblogs_code">
<pre>$ docker build -t certbot:<span style="color: rgba(128, 0, 128, 1)">1.0</span> .</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">然后在 certbot 目录下创建自动更新证书的脚本 renew_cert.sh,内容如下:</span></p>
<div class="cnblogs_code">
<pre>#!/bin/<span style="color: rgba(0, 0, 0, 1)">bash
WEBDIR</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
LIST</span>=(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">filterinto.com</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">www.filterinto.com</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
LED_LIST</span>=<span style="color: rgba(0, 0, 0, 1)">()
WWW_ROOT</span>=/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html
</span><span style="color: rgba(0, 0, 255, 1)">for</span> domain <span style="color: rgba(0, 0, 255, 1)">in</span> ${LIST[@]};<span style="color: rgba(0, 0, 255, 1)">do</span><span style="color: rgba(0, 0, 0, 1)">
    docker run \
      </span>--<span style="color: rgba(0, 0, 255, 1)">rm</span><span style="color: rgba(0, 0, 0, 1)"> \
      </span>-v ${WEBDIR}/nginx/conf.crt:/etc/<span style="color: rgba(0, 0, 0, 1)">letsencrypt \
      </span>-v ${WEBDIR}/logs/letsencrypt:/var/log/<span style="color: rgba(0, 0, 0, 1)">letsencrypt \
      </span>-v ${WEBDIR}/nginx/<span style="color: rgba(0, 0, 0, 1)">html:${WWW_ROOT} \
      certbot:</span><span style="color: rgba(128, 0, 128, 1)">1.0</span><span style="color: rgba(0, 0, 0, 1)"> \
      certbot certonly </span>--verbose --noninteractive --quiet --agree-<span style="color: rgba(0, 0, 0, 1)">tos \
      </span>--webroot -<span style="color: rgba(0, 0, 255, 1)">w</span><span style="color: rgba(0, 0, 0, 1)"> ${WWW_ROOT} \
      </span>--email=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nick.li@grapecity.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> \
      </span>-d <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$domain</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    CODE</span>=$?
    <span style="color: rgba(0, 0, 255, 1)">if</span> [ $CODE -ne <span style="color: rgba(128, 0, 128, 1)">0</span> ]; <span style="color: rgba(0, 0, 255, 1)">then</span><span style="color: rgba(0, 0, 0, 1)">
      FAILED_LIST</span>+=<span style="color: rgba(0, 0, 0, 1)">($domain)
    </span><span style="color: rgba(0, 0, 255, 1)">fi</span>
<span style="color: rgba(0, 0, 255, 1)">done</span><span style="color: rgba(0, 0, 0, 1)">

# output failed domains
</span><span style="color: rgba(0, 0, 255, 1)">if</span> [ ${#FAILED_LIST[@]} -ne <span style="color: rgba(128, 0, 128, 1)">0</span> ];<span style="color: rgba(0, 0, 255, 1)">then</span>
    <span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">failed domain:</span><span style="color: rgba(128, 0, 0, 1)">'</span>
    <span style="color: rgba(0, 0, 255, 1)">for</span> (( i=<span style="color: rgba(128, 0, 128, 1)">0</span>; i&lt;${#FAILED_LIST[@]}; i++<span style="color: rgba(0, 0, 0, 1)"> ));
    </span><span style="color: rgba(0, 0, 255, 1)">do</span>
      <span style="color: rgba(0, 0, 255, 1)">echo</span><span style="color: rgba(0, 0, 0, 1)"> ${FAILED_LIST[$i]}
    </span><span style="color: rgba(0, 0, 255, 1)">done</span>
<span style="color: rgba(0, 0, 255, 1)">fi</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">在用户的家目录中执行 ./renew_cert.sh /home/nick 命令就可以生成新的证书(/home/nick 为当前用户的家目录)。生成的证书被保存在 /home/nick/nginx/conf.crt/live 目录下,以域名命名的目录下保存着该域名的证书:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135838388-1435753084.png"></span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">然后去检查下 nginx/html 目录,发现多了一个隐藏的 .well-known 目录,这个目录就是在生成证书时创建的:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610135927844-330349561.png"></span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">有了 SSL/TLS 证书,接下来我们就可以配置 https 站点了。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">为站点配置 SSL/TLS 证书</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">有了 SSL/TLS 证书,接下来更新 nginx 的配置文件就可以了,更新 nginx/conf.d/default.conf 的内容如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">upstream web{
    server myweb:</span><span style="color: rgba(128, 0, 128, 1)">3000</span><span style="color: rgba(0, 0, 0, 1)">;
}

server {
    listen      </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)">;
    listen      [::]:</span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)">;
    server_name filterinto.com www.filterinto.com;

    location </span>^~ /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      default_type </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/plain</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      root </span>/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html;
    }
    location </span>= /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      return </span><span style="color: rgba(128, 0, 128, 1)">404</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    return </span><span style="color: rgba(128, 0, 128, 1)">301</span> https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$server_name$request_uri;</span>
<span style="color: rgba(0, 0, 0, 1)">}
server {
    listen      </span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)">;
    listen      [::]:</span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)">;
    server_name filterinto.com;

    # enable ssl
    ssl                     on;
    ssl_protocols TLSv1 TLSv1.</span><span style="color: rgba(128, 0, 128, 1)">1</span> TLSv1.<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">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</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    # config ssl certificate
<span style="color: rgba(255, 0, 0, 1)">   <strong>ssl_certificate         conf.crt</strong></span></span><span style="color: rgba(255, 0, 0, 1)"><strong>/live/filterinto.com/fullchain.pem;
    ssl_certificate_key       conf.crt/live/filterinto.com/</strong></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong>privkey.pem;</strong></span>

    location </span>^~ /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      default_type </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/plain</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      root </span>/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html;
    }
    location </span>= /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
            return </span><span style="color: rgba(128, 0, 128, 1)">404</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    location </span>/<span style="color: rgba(0, 0, 0, 1)"> {
      proxy_pass http:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">web;</span>
<span style="color: rgba(0, 0, 0, 1)">    }
}
server {
    listen      </span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)">;
    listen      [::]:</span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)">;
    server_name www.filterinto.com;

    # enable ssl
    ssl                     on;
    ssl_protocols TLSv1 TLSv1.</span><span style="color: rgba(128, 0, 128, 1)">1</span> TLSv1.<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">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</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    # config ssl certificate
   <strong><span style="color: rgba(255, 0, 0, 1)"> ssl_certificate         conf.crt</span></strong></span><strong><span style="color: rgba(255, 0, 0, 1)">/live/www.filterinto.com/fullchain.pem;
    ssl_certificate_key       conf.crt/live/www.filterinto.com/</span></strong><span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 0, 1)">privkey.pem;</span></strong>

    location </span>^~ /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
      default_type </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text/plain</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      root </span>/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html;
    }
    location </span>= /.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
            return </span><span style="color: rgba(128, 0, 128, 1)">404</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    location </span>/<span style="color: rgba(0, 0, 0, 1)"> {
      proxy_pass http:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">web;</span>
<span style="color: rgba(0, 0, 0, 1)">    }
}</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">然后删除容器 gateway 并用下面的脚本重新创建:</span></p>
<div class="cnblogs_code">
<pre>$ docker run -<span style="color: rgba(0, 0, 0, 1)">d \
    </span>-p <span style="color: rgba(128, 0, 128, 1)">80</span>:<span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)"> \
    </span>-p <span style="color: rgba(128, 0, 128, 1)">443</span>:<span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)"> \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/conf.d:/etc/nginx/<span style="color: rgba(0, 0, 0, 1)">conf.d:ro \
    </span><strong><span style="color: rgba(255, 0, 0, 1)">-v $(pwd)/nginx/conf.crt:/etc/nginx/conf.crt:ro \
    </span></strong>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/nginx.conf:/etc/nginx/<span style="color: rgba(0, 0, 0, 1)">nginx.conf:ro \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/logs/nginx:/var/log/<span style="color: rgba(0, 0, 0, 1)">nginx \
    </span>-v $(<span style="color: rgba(0, 0, 255, 1)">pwd</span>)/nginx/html:/usr/share/nginx/<span style="color: rgba(0, 0, 0, 1)">html \
    </span>--restart=<span style="color: rgba(0, 0, 0, 1)">always \
    </span>--name=<span style="color: rgba(0, 0, 0, 1)">gateway \
    </span>--network=<span style="color: rgba(0, 0, 0, 1)">webnet \
    nginx:</span><span style="color: rgba(128, 0, 128, 1)">1.14</span></pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">现在就只能通过 https 来访问站点了:</span></p>
<p><span style="font-family: Microsoft YaHei; font-size: 15px"><img src="https://images2018.cnblogs.com/blog/952033/201806/952033-20180610140101538-856991840.png"></span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">自动更新证书</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">Let's Encrypt 提供的 SSL/TLS 证书期限只有三个月,每过三个月要手动更新一次证书也够呛的,下面我们介绍自动更新证书的方法。</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">其实我们的配置已经为自动化更新证书提供了最大的便利(其实是使用 docker 带来的便利),在定时任务中添加下面两条记录就可以了:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 128, 1)">0</span> <span style="color: rgba(128, 0, 128, 1)">0</span> <span style="color: rgba(128, 0, 128, 1)">1</span> * * /home/nick/certbot/renew_cert.<span style="color: rgba(0, 0, 255, 1)">sh</span> /home/nick &gt;&gt; /home/nick/logs/cert.log <span style="color: rgba(128, 0, 128, 1)">2</span>&gt;&gt; /home/nick/logs/<span style="color: rgba(0, 0, 0, 1)">cert.error.log
</span><span style="color: rgba(128, 0, 128, 1)">0</span> <span style="color: rgba(128, 0, 128, 1)">1</span> <span style="color: rgba(128, 0, 128, 1)">1</span> * * docker exec gateway nginx -s reload</pre>
</div>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">每月 1 号的 0 点更新证书,一个小时后 reload nginx 的配置。</span></p>
<h1><span style="font-family: Microsoft YaHei; font-size: 18pt">总结</span></h1>
<p><span style="font-family: Microsoft YaHei; font-size: 15px">Let's Encrypt 是一个非常棒的网站,对于初学者和个人来说,能够帮助我们轻松的实现 HTTPS 站点(还是免费的)!在方便的同时,其隐患也是显而易见的:既然谁都可以无门槛的获得 SSL/TLS 证书,那么非法网站也可以通过它把自己伪装成看上去合法的站点。 所以千万不要片面的认为 HTTPS 站点就是安全的!</span></p>
<p><strong><span style="font-family: Microsoft YaHei; font-size: 15px">参考:</span></strong><br><span style="font-family: Microsoft YaHei; font-size: 15px">Setting up HTTPS on Nginx using Let’s Encrypt</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">在 docker nginx 下使用 docker let's encrypt</span><br><span style="font-family: Microsoft YaHei; font-size: 15px">How to Set Up Free SSL Certificates from Let's Encrypt using Docker and Nginx</span></p>

</div>
<div id="MySignature" role="contentinfo">
    <div>作者:sparkdev</div>
<div>出处:http://www.cnblogs.com/sparkdev/</div>
<div>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。</div><br><br>
来源:https://www.cnblogs.com/sparkdev/p/9163162.html
頁: [1]
查看完整版本: 为 docker 中的 nginx 配置 https