为什么Docker LNMP必须配置SSL证书
现在网站不上HTTPS基本等于裸奔——浏览器会标记"不安全",搜索引擎排名也会受影响。对于Docker LNMP环境来说,配置SSL证书有两个核心优势:数据传输加密保护用户隐私,HTTPS是Google等搜索引擎的排名加分项。
Let's Encrypt提供免费SSL证书,配合Docker容器化的Certbot工具,整个申请和续期过程都能自动化完成,不需要花钱买证书,也不需要手动续期。
整体方案架构
Docker LNMP配置SSL的核心思路:Nginx容器负责HTTPS服务 + Certbot容器负责证书申请与续期,两者通过共享卷交换证书文件。
- Nginx容器:监听80端口处理HTTP请求和ACME验证,监听443端口提供HTTPS服务
- Certbot容器:通过webroot方式验证域名所有权,证书文件写入共享卷
- 共享卷:Nginx读取Certbot生成的证书,实现无缝配合
一、项目目录结构准备
先搭建好Docker LNMP的目录结构,重点增加certbot相关的挂载目录:
docker-lnmp/
├── docker-compose.yml
├── nginx/
│ ├── conf.d/
│ │ └── default.conf
│ └── nginx.conf
├── php/
│ └── Dockerfile
├── mysql/
│ └── data/
├── www/
│ └── html/ # 网站根目录
├── certbot/
│ ├── conf/ # 证书文件存放
│ └── www/ # ACME验证目录
└── scripts/
└── renew-cert.sh # 续期脚本
二、docker-compose.yml配置
在原有LNMP基础上,增加Certbot服务,并添加证书共享卷:
version: '3.8'
services:
nginx:
image: nginx:1.24-alpine
container_name: lnmp-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./www/html:/usr/share/nginx/html
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
depends_on:
- php
restart: unless-stopped
php:
build: ./php
container_name: lnmp-php
volumes:
- ./www/html:/usr/share/nginx/html
restart: unless-stopped
mysql:
image: mysql:8.0
container_name: lnmp-mysql
environment:
MYSQL_ROOT_PASSWORD: your_root_password
volumes:
- ./mysql/data:/var/lib/mysql
restart: unless-stopped
certbot:
image: certbot/certbot
container_name: lnmp-certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do sleep 6h & wait $${!}; certbot renew; done;'"
restart: unless-stopped
关键点说明:
- Nginx和Certbot共享
/etc/letsencrypt和/var/www/certbot两个卷 - Certbot容器内置自动续期循环,每6小时检查一次证书是否需要更新
- 先只启动Nginx申请证书,证书到手后再开启HTTPS配置
三、Nginx配置(申请证书阶段)
申请证书前,Nginx需要先配置HTTP服务,让Certbot能通过webroot方式验证域名:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Certbot ACME验证路径
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# 其他请求重定向到HTTPS(证书申请成功后再开启)
location / {
root /usr/share/nginx/html;
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
注意:/.well-known/acme-challenge/这个location是Let's Encrypt验证域名所有权的核心,必须指向Certbot的验证目录。
四、申请SSL证书
先启动Nginx服务,再运行Certbot申请证书:
# 启动Nginx
docker-compose up -d nginx
# 申请证书(首次申请)
docker-compose run --rm certbot certonly \
--webroot \
--webroot-path=/var/www/certbot \
--email your-email@example.com \
--agree-tos \
--no-eff-email \
-d yourdomain.com \
-d www.yourdomain.com
申请成功后,证书文件会保存在./certbot/conf/live/yourdomain.com/目录下:
fullchain.pem— 完整证书链privkey.pem— 私钥文件
五、Nginx配置(HTTPS阶段)
证书到手后,修改Nginx配置开启HTTPS,并配置安全参数:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# HTTP强制跳转HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL证书配置
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SSL安全参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS(可选,建议开启)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /usr/share/nginx/html;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
六、自动续期配置
Let's Encrypt证书有效期90天,必须定期续期。Docker环境下有两种自动续期方案:
方案1:Certbot容器内置续期
上面的docker-compose.yml中,Certbot容器的entrypoint已经配置了每6小时自动检查续期的循环。Nginx需要配合重载配置:
# 在Nginx容器中添加续期后重载的定时任务
docker-compose exec nginx sh -c "echo '0 0 * * * nginx -s reload' >> /etc/crontabs/root"
方案2:宿主机cron续期脚本(推荐)
更可控的方式是在宿主机设置cron任务:
#!/bin/bash
# renew-cert.sh
cd /path/to/docker-lnmp
docker-compose run --rm certbot renew
docker-compose exec nginx nginx -s reload
添加cron定时任务:
# 每天凌晨2点检查续期
0 2 * * * /path/to/docker-lnmp/scripts/renew-cert.sh >> /var/log/certbot-renew.log 2>&1
七、常见问题排查
1. 证书申请失败:Connection refused
检查80端口是否对外开放,域名DNS是否正确解析到服务器IP。Let's Encrypt需要通过HTTP访问你的服务器完成验证。
2. 证书申请失败:Forbidden
检查Nginx配置中/.well-known/acme-challenge/的root路径是否指向/var/www/certbot,以及该目录是否有读取权限。
3. HTTPS访问提示证书无效
确认Nginx配置中ssl_certificate和ssl_certificate_key路径正确,使用docker-compose exec nginx nginx -t测试配置是否正常。
4. 续期失败
手动执行docker-compose run --rm certbot renew --dry-run测试续期流程,查看具体错误信息。
八、SSL安全评分优化
配置完成后,建议到SSL Labs测试你的SSL配置评分。几个提升评分的关键点:
- 禁用TLSv1.0和TLSv1.1,只保留TLSv1.2和TLSv1.3
- 使用ECDHE密钥交换算法实现前向保密
- 开启OCSP Stapling减少证书验证延迟
- 配置HSTS告诉浏览器始终使用HTTPS
总结
Docker LNMP配置SSL证书并不复杂,核心就是Nginx和Certbot通过共享卷协作:Nginx提供验证路径和HTTPS服务,Certbot负责证书申请和续期。整个流程可以总结为三步:先配HTTP跑通验证 → 申请证书 → 再配HTTPS并设置自动续期。一次配置,长期自动运行,告别手动续证书的烦恼。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论