惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
Jina AI
Jina AI
雷峰网
雷峰网
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
美团技术团队
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
博客园 - Franky
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
量子位
IT之家
IT之家
人人都是产品经理
人人都是产品经理
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

轶哥博客

blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog
blog
2020-03-07 · via 轶哥博客

MySQL定时备份程序中我有提到一个基于Docker快速生成SSL证书的方式。该文章整理了该方案的详细教程。

基于Let's Encrypt免费SSL证书。

官方介绍

docker-letsencrypt-nginx-proxy-companion

官方示例

使用方法

非docker-compose模式下。

第一步:执行下述两条命令

docker run --detach \
    --name nginx-proxy \
    --publish 80:80 \
    --publish 443:443 \
    -e ENABLE_IPV6=true \
    --volume /etc/nginx/certs \
    --volume /etc/nginx/vhost.d \
    --volume /usr/share/nginx/html \
    --volume /var/run/docker.sock:/tmp/docker.sock:ro \
    jwilder/nginx-proxy

docker run --detach \
    --name nginx-proxy-acme \
    --volumes-from nginx-proxy \
    --volume /var/run/docker.sock:/var/run/docker.sock:ro \
    --volume acme:/etc/acme.sh \
    --env "DEFAULT_EMAIL=mail@yourdomain.tld" \
    nginxproxy/acme-companion

第二步:启动项目时加上相关环境变量

以Nginx静态资源站点为例:

docker run -itd --restart always \
      -v 你的静态资源文件:/usr/share/nginx/html \
    --env "VIRTUAL_PORT=80" \
    --env "VIRTUAL_HOST=你的域名" \
    --env "LETSENCRYPT_HOST=你的域名" \
    nginx

此时,直接访问LETSENCRYPT_HOST中的域名,显示证书正常即可(可能有一分钟左右延迟)。

第三步:重复第二步

是不是很简单,几乎零配置,连修改nginx配置的工夫都省了。

环境变量说明

VIRTUAL_PORT:您的项目监听的端口。这里有个坑,某些情况下监听端口不一定成功。建议每次暴露内部端口,例如增加-p 80参数,确保监听一定成功。详见Node.js示例。

VIRTUAL_HOST:站点域名,可多个,以英文逗号分割。

LETSENCRYPT_HOST:申请SSL证书的域名,可多个,以英文逗号分割。

LETSENCRYPT_EMAIL:通知邮箱,选填。(很多情况下填了也没用)

docker-compose示例参考:https://github.com/nginx-proxy/docker-letsencrypt-nginx-proxy-companion/blob/master/docs/Docker-Compose.md

更多示例用法

Node.js 项目

docker run -itd --name appointment-service --restart always \
    -m 1024m \
    --link mysql:mysql \
    -p 80 \
    --env "VIRTUAL_PORT=80" \
    --env "VIRTUAL_HOST=appointment.api.ykfz.pw" \
    --env "LETSENCRYPT_HOST=appointment.api.ykfz.pw" \
    -v /etc/localtime:/etc/localtime:ro \
    -v /root/site/appointment-service:/root \
    -w /root \
    --restart=always node:13.7.0 npm start

说明:-p 80参数将明确暴露容器内80端口,随机转发到宿主机某一端口。缺少该参数将可能导致监听失败出现502报错

泛解析用法

由于申请免费通配符证书需要ACMEv2支持,以上方法暂不适用于通配符域名(原因 2021年08月25日14:03:29更新:nginxproxy/acme-companion 或已经支持泛域名。

解决思路:

  1. 参考另外一篇博文配置自动续期的免费通配符SSL证书
  2. 未测试的方案:https://github.com/adferrand/docker-letsencrypt-dns
  3. 推荐搭配acme.sh实现该需求。

思路3具体操作如下:

  1. 按照acme.sh说明安装acme.sh。通常只需要执行curl https://get.acme.sh | sh命令。
  2. 根据https://github.com/acmesh-official/acme.sh/wiki/dnsapi 寻找你的域名DNS提供商,参照说明配置API账号。例如腾讯云则参考DNSPod配置方式,阿里云则参考第十一条Aliyun的配置方式。如果您使用的DNS解析提供商不在该列表,可以在github搜搜看。
  3. 生成SSL证书。例如acme.sh --issue --dns dns_dp -d *.app.ykfz.pw

将得到:

[2020年 03月 07日 星期六 21:40:19 CST] Your cert is in  /root/.acme.sh/*.app.ykfz.pw/*.app.ykfz.pw.cer
[2020年 03月 07日 星期六 21:40:19 CST] Your cert key is in  /root/.acme.sh/*.app.ykfz.pw/*.app.ykfz.pw.key
[2020年 03月 07日 星期六 21:40:19 CST] The intermediate CA cert is in  /root/.acme.sh/*.app.ykfz.pw/ca.cer
[2020年 03月 07日 星期六 21:40:19 CST] And the full chain certs is there:  /root/.acme.sh/*.app.ykfz.pw/fullchain.cer
  1. 下载此代码https://gist.github.com/yi-ge/6c13dfddabd128a630bea9481ac8fb98nginx.tmpl文件或参考jtegtmeier提供的配置方法:https://github.com/nginx-proxy/nginx-proxy/commit/07655df85884b4ee7937a422ccd33b413b584a02

感谢jtegtmeier提供的方案!

  1. 以类似下述命令的方式启动nginx-proxy
docker run --detach \
    --name nginx-proxy \
    --publish 80:80 \
    --publish 443:443 \
    --volume /etc/nginx/certs \
    --volume /etc/nginx/vhost.d \
    --volume /usr/share/nginx/html \
    --volume /var/run/docker.sock:/tmp/docker.sock:ro \
    -v `pwd`/nginx.tmpl:/app/nginx.tmpl \
    -v /root/.acme.sh:/root/.acme.sh \
    jwilder/nginx-proxy

增加了acme路径映射,请确保nginx.tmpl在执行文件的目录下。

  1. 增加环境变量配置并启动容器。
docker run -itd -m 1024m \
  --restart=always \
  --name appointment-ui \
  -v /root/site/appointment-ui:/usr/share/nginx/html \
  --env "VIRTUAL_HOST=*.app.ykfz.pw" \
  --env "CERT_PATHNAME=/root/.acme.sh/*.app.ykfz.pw/*.app.ykfz.pw.cer" \
  --env "PRIVATE_KEY_PATHNAME=/root/.acme.sh/*.app.ykfz.pw/*.app.ykfz.pw.key" \
  --env "CHAIN_PATHNAME=/root/.acme.sh/*.app.ykfz.pw/fullchain.cer" \
  nginx 

请参考第二步得到的证书,对应设置证书路径。

Custom pathnames are set on the virtual hosts using these environment variables:

  • CERT_PATHNAME=/path/to/cert
  • PRIVATE_KEY_PATHNAME=/path/to/key
  • CHAIN_PATHNAME=/path/to/chain

注意,此处有个坑。请检查crontab配置,在自动更新SSL证书的配置下方增加nginx重启指令。

例如:

49 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
55 0 * * * /usr/bin/docker restart nginx-proxy

如果未使用nginx-proxy(即使用的是本地nginx),则参考添加如下命令:

17 0 1 * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
22 0 1 * * /use/sbin/nginx -s reload

配置完毕。

总结: 免费泛解析SSL证书必须修改DNS进行验证,每个季度一次。无论是手工修改DNS还是通过DNS API,都请做一个TODO List,在3个月后检查一下自己的网站是否正常运行。