3. 部署nginx反向代理 + ssl证书

  • nginx-proxy 是一个自动反向代理

  • letsencrypt-nginx-proxy-companion 自动部署 ssl 证书

两个相结合后, 只需要配置容器的环境变量 VIRTUAL_HOST=www.xxx.com 就能使用 http://www.xxx.com 访问当前容器。 当也配置 LETSENCRYPT_HOST 后,访问 http 就会跳转到 https 访问。

3.1. 前期准备

nginx-proxy 创建所需要的三个基础 vloums:

# /srv/nginx-proxy/nginx
├── certs
├── html
└── vhost.d

因为这两个应用是一组的,所以把这两个文件当成是一个 stack 制作文件 nginx.yml 配置成文件方便管理:

# nginx-proxy-letsencrypt.yml

version: "3.5"
services:
nginx-proxy-letsencrypt:
   image: jrcs/letsencrypt-nginx-proxy-companion
   environment:
      - DEFAULT_EMAIL=1503319119@qq.com
   volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /srv/nginx-proxy/nginx/certs:/etc/nginx/certs
      - /srv/nginx-proxy/nginx/vhost.d:/etc/nginx/vhost.d
      - /srv/nginx-proxy/nginx/html:/usr/share/nginx/html
   networks:
      - www_net
   depends_on:
      - nginx-proxy
   deploy:
      mode: global
      placement:
      constraints:
         - node.role == manager

nginx-proxy:
   image: jwilder/nginx-proxy
   ports:
      - mode: host
        protocol: tcp
        published: 80
        target: 80
      - mode: host
        protocol: tcp
        published: 443
        target: 443
   volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/nginx-proxy/nginx/certs:/etc/nginx/certs
      - /srv/nginx-proxy/nginx/vhost.d:/etc/nginx/vhost.d
      - /srv/nginx-proxy/nginx/html:/usr/share/nginx/html
   networks:
      - www_net
   labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
   deploy:
      mode: global
      placement:
      constraints:
         - node.role == manager

networks:
www_net:
   external: true

上述配置文件需要注意的几个地方:

  • nginx-proxy 的 ports 采用长配置方法,如果不这样配置 nginx 他接收到的请求地址都是主机的IP,设置后就能获取到用户真的的IP地址

  • nginx-proxy 的 labels 配置了 com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true 这样 nginx-proxy-letsencrypt 才会找到 nginx-porxy 这个容器去抓取数据

  • nginx-proxy-letsencrypt 是依赖与 nginx-proxy 的, 所以确保 nginx-proxy 先启动。

3.2. 部署nginx-proxy, letsencrypt-nginx-proxy-companion

现在装有 Portainer,所以都可以直接在 Portainer 上部署。但是限于篇幅,接下来都直接放出命令行部署。 实际的情况下以文章开头的动动鼠标就完成运维是思想,介意大家直接在 Portainer 上配置部署。

1. 命令行部署:

$ docker stack deploy -c nginx-proxy-letsencrypt.yml nginx-proxy

2. portainer 管理面板部署

https://lsol-house-upload.oss-cn-hangzhou.aliyuncs.com/2019-01-28/nginx-proxy.png

点击 Deploy the stack 部署后就可以在 services 里面去查看了

3. 配置 Portainer 面板,https 域名访问

到此 portainer 的面板都是通过 http://ip:9000 来访问的, 但是实际场景是需要一个域名访问的, 接下来配置域名 http://p.xxx.com 访问

注意

前提是你有一个域名,并且指向到此台服务器上。要不然生成证书会验证不通过。

现在需要做的就是给 Portainer 配置环境变量,来达到域名访问。 更新现有的 Portainer 的配置有多种方法, 推荐修改 portainer-agent-stack.yml`:

# portainer-agent-stack.yml
...
portainer:
   image: portainer/portainer
   command: -H tcp://tasks.agent:9001 --tlsskipverify
   ports:
      - "9000:9000"
      - "8000:8000" # 只用到web管理界面,此处的8000可以删除。
   volumes:
      - portainer_data:/data
   environment:
      - VIRTUAL_HOST=p.xxx.com # 多个域名逗号隔开p.xxx.com,www.xxx.com
      - LETSENCRYPT_HOST=p.xxx.com # 多个域名逗号隔开p.xxx.com,www.xxx.com
   networks:
      - agent_network
      - www_net
   deploy:
      mode: replicated
      replicas: 1
      placement:
      constraints: [node.role == manager]
...

修改的地方就是在原有的 portainer-agent-stack.yml 上增加 environment 两个环境变量

4. 命令行更新:

$ docker stack deploy -c portainer-agent-stack.yml portainer

接下来等应用重启后就可以用 http://p.xxx.com 访问,他会自动跳转到 https://p.xxx.com 了。