用docker安装Nginx-proxy、Nginx,并使用letsencrypt-nginx-proxy-companion自动生成免费的SSL证书

前言 

有这么一个问题,能不能用一个统一的服务器来管理这些外网入口,从而在负载均衡、安全性、隔离性等问题上都有所保证? 答案就是用 nginx 反向代理,但 nginx 配置写起来也挺麻烦的,有没有能根据 docker-compose 上的配置自动生成 nginx 配置的东西?答案就是 nginx-proxy 。 除此之外,nginx-proxy 还能自动帮你从 Let's Encrypt 上申请免费的 HTTPS 证书,简直是不要太好用,不过因为申请证书要验证网站所有权,你的服务器必须要被外网访问到才行。

域名解析到服务器外网地址

nginx-proxy申请免费的 HTTPS 证书的时候,域名必须能够访问到服务器,所以我们第一步做域名解析,就是域名解析到服务器外网地址,比如我用的阿里云。 

80、443端口记得开启,阿里云服务器有时候会默认关闭,需要登录在阿里云控制台-安全组设置端口。

 

 

安装Nginx-proxy

创建Nginx-proxy的docker-compose.yml文件

# 创建nginx-proxy目录
mkdir -p  /home/docker/nginx-proxy
# 切换到nginx-proxy目录
cd /home/docker/nginx-proxy/
# 在nginx-proxy目录下,创建docker-compose.yml文件
touch docker-compose.yml
# 编辑docker-compose.yml文件
vim docker-compose.yml

docker-compose.yml内容如下:

version: "3"
services:
 nginx-proxy:
  image: jwilder/nginx-proxy
  container_name: nginx-proxy
  hostname: nginx-proxy
  restart: always
  ports:
   - 80:80
   - 443:443
  volumes:
   - /etc/localtime:/etc/localtime
   - ./dhparam:/etc/nginx/dhparam #docker内部数据卷挂载dhparam
   - ./conf:/etc/nginx/conf.d #docker内部数据卷挂载conf
   - ./vhost:/etc/nginx/vhost.d #docker内部数据卷挂载vhost
   - ./certs:/etc/nginx/certs:ro #docker内部数据卷挂载certs
   - ./logs:/var/log/nginx #docker内部数据卷挂载logs
   - ./html:/usr/share/nginx/html #docker内部数据卷挂载html
   - /home/web:/home/web #业务web页面挂载目录
   - /var/run/docker.sock:/tmp/docker.sock:ro #挂载宿主机docker.sock用于监听容器启动情况
  labels: # 设置一个标签
   - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
  environment:
   DEFAULT_HOST: fanyicloud.cn
 letsencrypt-nginx-proxy-companion:
  image: jrcs/letsencrypt-nginx-proxy-companion
  container_name: letsencrypt
  hostname: letsencrypt
  restart: always
  volumes:
   - ./conf:/etc/nginx/nginx.conf
   - ./certs:/etc/nginx/certs:rw
   - ./vhost:/etc/nginx/vhost.d
   - ./html:/usr/share/nginx/html
   - /var/run/docker.sock:/var/run/docker.sock:ro
  environment:
   DEFAULT_EMAIL: 5525124@qq.com
networks: #设置内部网络nginx-proxy
  default:
    external:
      name: nginx-proxy

其中letsencrypt-nginx-proxy-companion可以自动生成免费的SSL证书

创建网络Nginx-proxy

docker network create nginx-proxy

启动Nginx-proxy(build操作,一定要在docker-compose.yml同级目录)

docker-compose up -d --build

查看容器是否创建成功

docker ps

输出下面的内容,就创建成功了

CONTAINER ID   IMAGE                                    COMMAND                  CREATED       STATUS       PORTS                                      NAMES
2cf27277cd30   jwilder/nginx-proxy                      "/app/docker-entrypo…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx-proxy
371a4b0f01bd   jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   2 hours ago   Up 2 hours                                              letsencrypt

相关命令

# 停止命令
docker-compose stop nginx-proxy
# 启动命令
docker-compose start nginx-proxy
# 停止并启动命令
docker-compose restart nginx-proxy

安装Nginx

创建Nginx的docker-compose.yml文件

# 创建nginx目录
mkdir -p  /home/docker/nginx
# 切换到nginx目录
cd /home/docker/nginx/
# 在nginx目录下,创建docker-compose.yml文件
touch docker-compose.yml
# 编辑docker-compose.yml文件
vim docker-compose.yml

docker-compose.yml内容如下:

version: '3'
services:
   nginx:
       image: "docker.io/nginx:stable"
       container_name: nginx
       hostname: nginx
       restart: always
       volumes:
         - /etc/localtime:/etc/localtime
         - $PWD/conf.d:/etc/nginx/conf.d
         - $PWD/html:/usr/share/nginx/html
         - $PWD/logs:/var/log/nginx
         - /home/web:/home/web
       expose:
         - 80
       environment:
          - VIRTUAL_HOST=manage.fanyicloud.cn,api.manage.fanyicloud.cn
          - LETSENCRYPT_HOST=manage.fanyicloud.cn,api.manage.fanyicloud.cn
          - LETSENCRYPT_EMAIL=5525124@qq.com
networks: #设置内部网络nginx-proxy
 default:
   external:
     name: nginx-proxy

VIRTUAL_HOST 、 LETSENCRYPT_HOST 对应的你要映射的域名,多个以逗号分隔。作用是自动设置证书功能

启动Nginx

docker-compose up -d --build

查看容器是否创建成功

docker ps

输出下面的内容,就创建成功了

CONTAINER ID   IMAGE                                    COMMAND                  CREATED              STATUS              PORTS                                      NAMES
51e64d410acb   nginx:stable                             "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp                                     nginx                                        letsencrypt

相关命令

停止命令
docker-compose stop nginx
启动命令
docker-compose start nginx
停止并启动命令
docker-compose restart nginx

配置域名conf文件

域名映射无非两种情况,一种是把域名映射到服务器特定文件夹下,比如我想把 manage.fanyicloud.cn 这个域名映射到服务器的/home/web/manage/index.html。
另一种是把域名映射到服务器特定端口下,比如我想把 api.manage.fanyicloud.cn 这个域名映射到服务器9090端口。

域名映射到服务器特定文件夹

在conf.d目录下创建manage.fanyicloud.cn.conf文件

# 进入nginx文件夹下的conf.d目录
cd /home/docker/nginx/conf.d
# 创建manage.fanyicloud.cn.conf文件
touch manage.fanyicloud.cn.conf
# 编辑conf文件
vim manage.fanyicloud.cn.conf

manage.fanyicloud.cn.conf内容如下:

map $http_x_forwarded_proto $proxy_x_forwarded_proto {
 default $http_x_forwarded_proto;
 ''      $scheme;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
 default $http_x_forwarded_port;
 ''      $server_port;
}
map $http_upgrade $proxy_connection {
 default upgrade;
 '' close;
}
map $scheme $proxy_x_forwarded_ssl {
 default off;
 https on;
}
server {
       listen 80;
       # [manage.fanyicloud.cn]替换成自己的域名
       server_name manage.fanyicloud.cn;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# 设置上传文件大小
       client_max_body_size 10m;
# 开启压缩功能
gzip on;
gzip_min_length 1k;
gzip_buffers 4 32k;
gzip_comp_level 5;
       gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg image/gif image/png;
       gzip_vary off;
       gzip_disable "MSIE [1-6]\.";

location / {
        # [/home/web/manage/]替换成自己的目录
        root /home/web/manage/;
        index  index.html index.htm;
 try_files $uri $uri/ /index.html;
    }
}

域名映射到服务器特定端口

在conf.d目录下创建api.manage.fanyicloud.cn.conf文件

# 进入nginx文件夹下的conf.d目录
cd /home/docker/nginx/conf.d
# 创建api.manage.fanyicloud.cn.conf文件
touch api.manage.fanyicloud.cn.conf
# 编辑conf文件
vim api.manage.fanyicloud.cn.conf

api.manage.fanyicloud.cn.conf内容如下:

# [api.manage]替换自己的域名前缀
upstream api.manage {
# [172.17.0.12:9090]替换成自己的内网地址和端口
   server 172.17.0.12:9090 weight=10;
}
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
 default $http_x_forwarded_proto;
 ''      $scheme;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
 default $http_x_forwarded_port;
 ''      $server_port;
}
map $http_upgrade $proxy_connection {
 default upgrade;
 '' close;
}
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
 default off;
 https on;
}
server {
       listen 80;
       server_name api.manage.fanyicloud.cn;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# 设置上传文件大小
       client_max_body_size 10m;
# 开启压缩功能
gzip on;
gzip_min_length 1k;
gzip_buffers 4 32k;
gzip_comp_level 5;
       gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg image/gif image/png;
       gzip_vary off;
       gzip_disable "MSIE [1-6]\.";
location / {
            # [api.manage]替换自己的域名前缀
               proxy_pass http://api.manage/;
       }
}

构建并重启nginx

配置完域名后,都需要构建并重启nginx

# 进入nginx文件夹
cd /home/docker/nginx
docker-compose up --build
docker restart nginx

 

强制更新域名证书

container_id 为 jrcs/letsencrypt-nginx-proxy-companion 的 container_id,等待执行完成。

docker exec -it container_id  /app/force_renew

执行过程

[root@kuaijian docker]# docker exec -it ca224b0b06a7  /app/force_renew
Creating/renewal www.qmyibang.cn certificates... (www.qmyibang.cn qmyibang.cn api.qmyibang.cn minio.qmyibang.cn xxl-job.qmyibang.cn tool.qmyibang.cn file.qmyibang.cn)
[Tue Mar  5 06:58:34 UTC 2024] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Tue Mar  5 06:58:34 UTC 2024] Creating domain key
[Tue Mar  5 06:58:35 UTC 2024] The domain key is here: /etc/acme.sh/1085350540@qq.com/www.qmyibang.cn/www.qmyibang.cn.key
[Tue Mar  5 06:58:35 UTC 2024] Multi domain='DNS:www.qmyibang.cn,DNS:qmyibang.cn,DNS:api.qmyibang.cn,DNS:minio.qmyibang.cn,DNS:xxl-job.qmyibang.cn,DNS:tool.qmyibang.cn,DNS:file.qmyibang.cn'
[Tue Mar  5 06:58:35 UTC 2024] Getting domain auth token for each domain
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='www.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='api.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='minio.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='xxl-job.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='tool.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] Getting webroot for domain='file.qmyibang.cn'
[Tue Mar  5 06:58:47 UTC 2024] www.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] api.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] minio.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] xxl-job.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] tool.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] file.qmyibang.cn is already verified, skip http-01.
[Tue Mar  5 06:58:47 UTC 2024] Verify finished, start to sign.
[Tue Mar  5 06:58:47 UTC 2024] Lets finalize the order.
[Tue Mar  5 06:58:47 UTC 2024] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/1406062616/249732136827'
[Tue Mar  5 06:58:53 UTC 2024] Downloading cert.
[Tue Mar  5 06:58:53 UTC 2024] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/032d76e8cb823e31607095ecbfd13e91bfb9'
[Tue Mar  5 06:58:54 UTC 2024] Cert success.
-----BEGIN CERTIFICATE-----
MIIGVTCCBT2gAwIBAgISAy126MuCPjFgcJXsv9E+kb+5MA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yNDAzMDUwNjAxNTRaFw0yNDA2MDMwNjAxNTNaMBoxGDAWBgNVBAMT
D3d3dy5xbXlpYmFuZy5jbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
AM2X/HwgO6DjjJWD99ZylkoeY8GuUeS1abs5MMZL2G+SPkkvOXQgwQL5ZHatc4tf
XV4Jy3h5FI8Aift7FUMXEXU+BmqTl4F0j7t8J4WnKbpwuoj2GXZxCQxjxpF+cH0a
1z1XUF0dVEZ2UccabJ2Q3rg1fWLEfrSuOnPUcXEEXuIpuIxFd2AyA6d0r7ShAm6K
RERiYfahJofUdJ7/Vz8fDWByOxDN/dKa0t6e54v5+S94sfFZzs96PutV+xIs387x
fQJvKMaZXBK6bvB9Bwcq51ruW/jwihnoubi1nE3QsQlyH6eO8cKerhPx/YObJ+1O
TyQvuHy0cV8OZXJQQ7bXoCRi7SvHnnvbqPQlxdT7oQCjRW+EB8HfNyO+rAqIU1Mm
XnR1KDQ7ZmjoeaiivPIGGcTr/KRqe+fM0zt+MxswAWeoEbRSdp7i033UB3dcwq4/
cEDhdmrm53oSNvxS9PBuYn4wXNqbV+a4y0aCzm8JZ/2ol9rKAlYrvcFeBlPgiqaR
IEIMe5q2KZRWJbr02h2kmVijVZxReoyGUcWecSsZVNQ+SXgydtv9smc2oarbsx9S
ZjKW2077KehHLfNQXHNwc85IVPPDCO83e1NkbzTE0ePftFMQjmu6FtYIOTTyk+13
4I6NoDNBVd6dloAN3L0/eoH1vfAzI8RIAS79hIJKk95FAgMBAAGjggJ7MIICdzAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG
A1UdEwEB/wQCMAAwHQYDVR0OBBYEFJxJX02q4PgAwOYs/h7WVXL1XgxkMB8GA1Ud
IwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggr
BgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRw
Oi8vcjMuaS5sZW5jci5vcmcvMIGEBgNVHREEfTB7gg9hcGkucW15aWJhbmcuY26C
EGZpbGUucW15aWJhbmcuY26CEW1pbmlvLnFteWliYW5nLmNuggtxbXlpYmFuZy5j
boIQdG9vbC5xbXlpYmFuZy5jboIPd3d3LnFteWliYW5nLmNughN4eGwtam9iLnFt
eWliYW5nLmNuMBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBAwYKKwYBBAHWeQIEAgSB
9ASB8QDvAHUAO1N3dT4tuYBOizBbBv5AO2fYT8P0x70ADS1yb+H61BcAAAGODWs4
0gAABAMARjBEAiBazfh+/2UhDZiPmywE8duMC2Oc5Sl80ZZ2LdeJBJazVwIgWzbN
UZ/XkI9AmCmGHF82yUW60ClwL8FFtXOLYB2pHDwAdgCi4r/WHt4vLweg1k5tN6fc
ZUOwxrUuotq3iviabfUX2AAAAY4Nazj2AAAEAwBHMEUCIQCE5pWG5rpn32RPoky6
2NszV7eVVfjXkPXrb1a9DTwMwAIgNLc/Ilm29mcLZ5gZXDKUj4CD9jxEW+zhH7ES
oFDnUzEwDQYJKoZIhvcNAQELBQADggEBAHLOsJjizB68+eJf6dEON+2f+ORPAfOQ
41xONjQkXOKqEw9WbfocS3kfpiGIXTAM5JkUx1W2I+5OvtT9chFrhohQU5i38lVC
sYG3evXE39/q7+5SojlNNnfR7pjl/Y6Wuv4Q7zXrzC2tpbkgbFa+FXyMxuZYJX03
Tasd5H8lQ/Mlih38Dq9dQ8JcmD4o+d3BphQzMb1BjfMB1gEXsIOwMsI7eu0OL6QV
j/aXdx8+wfZCoKR6Sl0TuqlS/x/vw5TQc7pwYG0pt7hY+L50Qg0S+AA23RVLYlDJ
njwkPzobgcAOyH+D2WvZqu+Xtn9uKiGaaGmuPleF5GcI3zF0P6GDQAA=
-----END CERTIFICATE-----
[Tue Mar  5 06:58:54 UTC 2024] Your cert is in  /etc/acme.sh/1085350540@qq.com/www.qmyibang.cn/www.qmyibang.cn.cer 
[Tue Mar  5 06:58:54 UTC 2024] Your cert key is in  /etc/acme.sh/1085350540@qq.com/www.qmyibang.cn/www.qmyibang.cn.key 
[Tue Mar  5 06:58:54 UTC 2024] The intermediate CA cert is in  /etc/acme.sh/1085350540@qq.com/www.qmyibang.cn/ca.cer 
[Tue Mar  5 06:58:54 UTC 2024] And the full chain certs is there:  /etc/acme.sh/1085350540@qq.com/www.qmyibang.cn/fullchain.cer 
[Tue Mar  5 06:58:54 UTC 2024] Installing cert to:/etc/nginx/certs/www.qmyibang.cn/cert.pem
[Tue Mar  5 06:58:54 UTC 2024] Installing CA to:/etc/nginx/certs/www.qmyibang.cn/chain.pem
[Tue Mar  5 06:58:54 UTC 2024] Installing key to:/etc/nginx/certs/www.qmyibang.cn/key.pem
[Tue Mar  5 06:58:54 UTC 2024] Installing full chain to:/etc/nginx/certs/www.qmyibang.cn/fullchain.pem
Reloading nginx proxy (399de6c56dde35be67d818532da961a6e39350d714f91871141d02972f562111)...
2024/03/05 14:58:55 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification ''

 

域名生成证书失败问题

查看/home/docker/nginx-proxy/certs/ 目录下是否自动生成了域名证书。
生成域名证书时间可能没那么快。
若长时间没有生成,大概率是有部分域名无法访问服务器,这时就要检查/home/docker/nginx/docker-compose.yml下,配置的域名,保证每个域名都能ping到服务器地址。


证书成功生成了,访问域名,查看是否变成了https请求。

版权声明:
作者:白纸画
链接:https://www.fanyicloud.cn/article-12.fan
来源:白纸画的博客
文章版权归作者所有,未经允许请勿转载。

THE END
二维码
打赏
下一篇>>