V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
neilp
V2EX  ›  SSL

自动生成免费 letsencrypt ssl 证书的全自动 nginx 反向代理 docker 镜像

  •  
  •   neilp · 2017-06-05 09:29:34 +08:00 · 7070 次点击
    这是一个创建于 2510 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文是介绍一个 docker 镜像的, 可以全自动实现反向代理, 并自动配置 ssl 证书.

    这里主要说两个问题:

    1. 对于只有一个公网 ip 的 docker host, 如果想在其中跑多个 web server 就有问题了, 因为 80 端口只能分配给一个 docker container. 怎么办, 一个好办法就是开一个反向代理. 把 80 端口分配给反向代理, 然后反向代理再根据域名分发给不同的内部 docker container. 看起来很简单对吧, 这没什么. 但是你一旦关闭重启内部的 web server container, 它的内部 ip 可能就会发生改变, 此时你不得不修改反向代理的配置, 并重新加载. 这些工作能不能自动完成 ?
    2. 第二个问题, 反向代理上能不能自动配置 ssl 证书. letsencrypt 不是有免费证书吗?

    很好, 这两个问题的答案都是肯定的. 分三步来说. 不用担心, 非常简单, 本文不会很长, 你会在几分钟只内完成.

    1. 先说第一个问题. 自动配置 docker 反向代理.

    用 nginx 镜像做一个反向代理, 并且能根据当前 docker host 的 container 的变化, 自动配置反向代理的 ip 和端口.

    这个问题其实早就有人解决了, 比如这两个项目:

    使用 docker api 可以自动监控 container 变化, 根据模板生成配置文件.

    https://github.com/jwilder/docker-gen

    作者另外的一个项目, 专门实现了 nginx 的反向代理.

    https://github.com/jwilder/nginx-proxy

    如果你只需要反向代理, 并不需要自动配置 ssl 的话, 本文你读到这里就可以了.

    2. 第二个问题, 为 nginx 反向代理自动配置 ssl

    为了自动配置 ssl, 我 fork 了上面的项目, 并做了少量修改, 加入了 acme.sh 的支持, 可以实现全自动 配置 ssl 证书.

    https://github.com/Neilpang/nginx-proxy

    并且已经在 docker hub 上发布了 trusted build:

    docker  pull  neilpang/nginx-proxy
    

    3. 第三步, 快速上手

    1. 首先在运行反向代理:

    
    mkdir proxy
    
    cd proxy
    
    
    docker run  \
    --rm -it  -d \
    -p 80:80 \
    -p 443:443  \
    -v /var/run/docker.sock:/tmp/docker.sock:ro  \
    -v $(pwd)/certs:/etc/nginx/certs \
    -v $(pwd)/acme:/acmecerts \
    neilpang/nginx-proxy
    
    

    稍微解释一下: 运行一个反向代理 并把 80443 端口都分配给它. 并且把 /var/run/docker.sock 传递给 container , 这是 docker api 操作文件.

    2. 现在可以运行你的 web server container 了:

    先把你的一个域名解析到 docker host ip, 例如: example.com

    然后, 我们随便启动一个 webserver:

    docker run --rm -it -d \
    -e VIRTUAL_HOST=example.com \
    --name test \
    httpd
    

    注意到上面的参数了吗: -e VIRTUAL_HOST=example.com.

    我们在上一步中运行的 neilpang/nginx-proxy 会自动监控这个 host 上的每一个 container 的变化. 如果发现有 VIRTUAL_HOST 变量, 就会自动配置反向代理.

    试试访问你的域名:

    http://example.com
    

    现在给这个反向代理配置 ssl:

    在此之前,请确保你的域名已经指向了主机 ip, 因为 letsencrypt 证书需要验证域名所有权.

    docker kill test
    
    docker run --rm -it -d \
    -e VIRTUAL_HOST=example.com \
    -e ENABLE_ACME=true \
    --name test \
    httpd
    
    

    注意到不同了吗, 仅仅多了一个变量: ENABLE_ACME=true

    大概几十秒之后, ssl 证书就会自动配置成功了.

    访问试试:

    https://example.com
    

    注意, 这个个证书是自动配置的, 今后会自动更新, 让你完全忘了它的存在.

    有多个域名绑定: 用逗号分隔.

    docker kill test
    
    docker run --rm -it -d \
    -e VIRTUAL_HOST=example.com,www.example.com \
    -e ENABLE_ACME=true \
    --name test \
    httpd
    
    

    另外, 这个镜像还有一个好处就是已经配置了从 http 跳转到 https, 并且自动启用 http 2.0

    原文链接: https://github.com/Neilpang/nginx-proxy/wiki

    希望能帮到更多人,节约你的时间和精力.

    欢迎大家转载 请保留链接.

    欢迎 star:

    https://github.com/Neilpang/nginx-proxy

    第 1 条附言  ·  2017-06-05 13:09:39 +08:00

    反代 非 80 的自定义端口:

    加上: VIRTUAL_PORT=8080 即可

    docker run --rm -it -d \
    -e VIRTUAL_HOST=example.com,www.example.com \
    -e ENABLE_ACME=true \
    -e VIRTUAL_PORT=8080 \
    --name test \
    httpd
    
    11 条回复    2019-09-12 16:10:56 +08:00
    momocraft
        1
    momocraft  
       2017-06-05 09:42:45 +08:00
    不错,有点服务发现的意思了.. 纯支持
    gamexg
        2
    gamexg  
       2017-06-05 10:06:29 +08:00
    有个问题,证书过期生成新证书后 nginx 并不会载入新证书。
    碰到 2 次了,浏览器打开提示证书错误,重启 nginx 才载入新证书。
    gamexg
        3
    gamexg  
       2017-06-05 10:09:45 +08:00
    @gamexg #2 额,看错了,不是一个项目,我说的是另一个 docker-letsencrypt-nginx-proxy-companion。
    ziyuan
        4
    ziyuan  
       2017-06-05 10:46:08 +08:00
    很不错,收藏了。
    kukat
        5
    kukat  
       2017-06-05 11:26:30 +08:00
    一直在用 https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion

    你这个好像不支持反代非 80 端口的容器?
    neilp
        6
    neilp  
    OP
       2017-06-05 13:10:09 +08:00
    @kukat
    可以的, 请看我的附加内容.
    jonechenug
        7
    jonechenug  
       2017-06-05 13:30:44 +08:00 via Android
    http://www.jianshu.com/p/2c6fd9e43aa7
    已经有人写过类似的教程了,还是图文。
    CEBBCAT
        8
    CEBBCAT  
       2017-06-05 15:26:07 +08:00 via Android
    看起来很适合我,又给我理由学习 docker,谢谢
    slime7
        9
    slime7  
       2017-08-12 16:40:44 +08:00
    虽然看到是坟,不过用了楼主的魔改反带,子域名在不同容器,主站开了 ssl 的话,不开启 acme 的其他域名也会自动 301 到 https 的链接。( aria2c 没开 ssl,webui-aria2 如果用 ssl 的话,连不上 rpc )
    lzs5240
        10
    lzs5240  
       2019-09-12 10:58:18 +08:00
    漂亮喔, 很有用, 多谢楼主的工作!
    lzs5240
        11
    lzs5240  
       2019-09-12 16:10:56 +08:00
    支持泛域名吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2844 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:24 · PVG 22:24 · LAX 07:24 · JFK 10:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.