大虾居

谈笑有鸿儒,往来无白丁。

0%

使用Docker快速部署Nginx反代,以及ACME自动续证书

前言

Nginx反向代理速度快,可以自定义各种转发规则,可以说是站长的好朋友。

acme.sh支持多个域名服务商的证书生成,让站长免费获取到ssl带来的安全性,也是不可或缺的好伙伴。

本文虾哥将本着DRY原则,让站长不需要记住部署nginx和acme的若干命令,快速搭建起安全实用的ssl反向代理服务器。

1. 准备

使用docker部署程序省去安装各种语言运行环境的麻烦,但docker本身还是需要准备一下。

下面介绍在centos7系统下安装docker 和 docker-compose的步骤。其他系统可以自行查找相关文档。

##1.1 安装docker

sudo yum install docker -y

安装完成后启动docker

sudo systemctl start docker
sudo systemctl enable docker	

##1.2安装docker-compose

docker-compose是python包,通过docker-compose,docker运行镜像的各种配置可以直接写入文件,重启和修改都非常容易。

# 通过yum安装pip官方没有直接提供rpm包,可以通过epel-release库安装
sudo yum install epel-release
sudo yum isntall python2-pip

sudo pip isntall docker-compose

这样就安装完成了,运行docker-compose命令行

docker-compose --help

1.3 准备程序运行目录

在决定运行docker-compose的任意路径创建好目录,以后我们程序运行相关的文件都保存在该路径下,如/app

mkdir /app
cd /app

在运行目录下创建nginx

2. acme.sh 申请证书并定期更新

2.1 acme.sh 申请证书

在程序运行路径下创建docker-compose.yml,通过docker-compose启动docker镜像的所有参数信息都会写入到该文件中

# /app/docker-compose.yml
version: '3'
services:
    acme.sh:
        image: neilpang/acme.sh
        volumes:
            - "./acme.sh:/acme.sh:z"
        environment:
            - CF_Key="xxx"
            - CF_Email="yyy"
        command: daemon

本文以cloudflare申请证书为例,其他域名服务商可以根据要求将相关的身份信息写入environment环境变量

运行acme生成证书

sudo docker-compose run acme.sh --issue --dns dns_cf -d xxx.example.com

域名和dns服务商参数根据实际情况自行修改。要使用cloudflare创建证书,需要把域名的ns指向到cloudflare并在cloudflare网站上申请管理员的key。运行完成后证书会保存在.acme.sh/xxx.example.com/文件夹下。

2.2 自动更新证书

这样免费申请的证书 只有3个月的有效期,通过command: daemon参数运行后,该进程会定期自动去域名服务商更新证书,再也不用为证书过期苦恼了。

docker-compose up -d

2. Nginx

Nginx提供了官方镜像
直接使用官方镜像就可以启动nginx服务。但要想根据我们的要求运行反向代理,还得编写一个配置文件。

创建/app/nginx/conf文件夹

mkdir -p /app/nginx/conf

在该文件夹下创建proxy.conf文件

# /app/nginx/conf/proxy.conf

server {
    listen 80;
    server_name   xxx.example.com;

    return 301 https://$host;
}

server {
    listen 443 ssl;
    server_name             xxx.example.com;
    ssl_certificate         /etc/nginx/certs/$server_name/fullchain.cer;
    ssl_certificate_key     /etc/nginx/certs/$server_name/$server_name.key;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        proxy_pass http://realserver;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_http_version      1.1;
        proxy_cache_bypass      $http_upgrade;

        proxy_set_header Upgrade                $http_upgrade;
        proxy_set_header Connection             "upgrade";
        proxy_set_header Host                   $host;
        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto      $scheme;
        proxy_set_header X-Forwarded-Host       $host;
        proxy_set_header X-Forwarded-Port       $server_port;

    }
}

这个配置启动了HSTS,强制使用https,增强了web服务的安全性。

把xxx.example.com替换成实际的域名。 realserver是反代对应的真实服务器地址。

要禁用直接用ip地址访问可以增加一个server节:

server {
    listen 80 default_server;
    return 444;
}

nginx在docker-compose中配置如下:

nginx:
    image: nginx
    ports:
        - "80:80"
        - "443:443"
    volumes:
        - "./acme.sh:/etc/nginx/certs"
        - "./nginx/conf:/etc/nginx/conf.d:z"
        - "./nginx/log/:/var/log/nginx/:z"
    environment:
        - ENV=production

通过docker-compose启动一组容器

docker-compose up -d

大功告成。

最后完整版的docker-compose文件如下:

# /app/docker-compose.yml
version: '3'
services:
    acme.sh:
        image: neilpang/acme.sh
        volumes:
            - "./acme.sh:/acme.sh:z"
        environment:
            - CF_Key="xxx"
            - CF_Email="yyy"
        command: daemon
    nginx:
        image: nginx
        network_mode: host
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - "./acme.sh:/etc/nginx/certs"
            - "./nginx/conf:/etc/nginx/conf.d:z"
            - "./nginx/log/:/var/log/nginx/:z"
        environment:
            - ENV=production