Nginx + Docker + SSL:搭建安全的 Web 服务

拥有一台云服务器和一个域名后,如何快速搭建一个支持 HTTPS 的安全 Web 服务?本文记录我在阿里云轻量应用服务器上使用 Docker 部署 Nginx 并配置免费 SSL 证书的完整过程。

📌 最终效果

通过 https://jhd1.com 和 https://www.jhd1.com 均可安全访问站点,SSL 证书由阿里云免费提供并自动续期。

环境准备

第一步:安装 Docker

# 安装 Docker(CentOS / Alibaba Cloud Linux)
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io

# 启动 Docker 并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
docker --version
docker run hello-world

第二步:准备 SSL 证书

在阿里云控制台申请免费 DV 证书后,下载 Nginx 格式的证书文件,通常包含:

将证书文件上传到服务器:

# 在服务器上创建证书存放目录
sudo mkdir -p /etc/nginx/ssl

# 上传证书文件(从本地上传)
scp cert.pem root@your-server:/etc/nginx/ssl/
scp key.pem root@your-server:/etc/nginx/ssl/

第三步:编写 Docker Compose 配置

# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:1.25-alpine
    container_name: nginx-web
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      # 网站文件目录
      - ./html:/usr/share/nginx/html:ro
      # Nginx 主配置文件
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # SSL 证书
      - /etc/nginx/ssl/cert.pem:/etc/nginx/ssl/cert.pem:ro
      - /etc/nginx/ssl/key.pem:/etc/nginx/ssl/key.pem:ro
      # 日志
      - ./logs:/var/log/nginx
    networks:
      - web-net

networks:
  web-net:
    driver: bridge

第四步:配置 Nginx

# nginx.conf
events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout 65;

    # HTTP → HTTPS 自动跳转
    server {
        listen 80;
        server_name jhd1.com www.jhd1.com;
        return 301 https://$host$request_uri;
    }

    # HTTPS 主配置
    server {
        listen 443 ssl http2;
        server_name jhd1.com www.jhd1.com;

        # SSL 证书配置
        ssl_certificate     /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/key.pem;

        # SSL 安全配置
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # 网站根目录
        root /usr/share/nginx/html;
        index index.html;

        # 日志
        access_log /var/log/nginx/access.log;
        error_log  /var/log/nginx/error.log;

        # 静态文件缓存
        location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff2)$ {
            expires 30d;
            add_header Cache-Control "public, immutable";
        }

        # 安全头
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
    }
}

第五步:部署网站

# 将网站文件放入 html 目录
# 你的 HTML/CSS/JS 文件应放在 ./html/ 下

# 启动容器
docker-compose up -d

# 检查状态
docker-compose ps
docker logs nginx-web

# 测试 HTTPS 访问
curl -I https://jhd1.com

第六步:验证与安全加固

  1. SSL 检测:使用 SSL Labs(ssllabs.com)检测 SSL 配置评分,目标达到 A+ 等级。
  2. HTTP 跳转:确认 http://jhd1.com 自动跳转到 https://jhd1.com。
  3. HSTS 配置:添加 Strict-Transport-Security 头,强制浏览器使用 HTTPS。
  4. 防火墙规则:在阿里云安全组中仅开放 80、443 和 22(SSH)端口。
# 添加 HSTS 头(在 nginx.conf 的 server 块中)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

常见问题排查

Q: 证书被浏览器提示不安全?

检查证书文件是否正确、域名是否匹配、证书是否在有效期内。使用 openssl s_client -connect jhd1.com:443 命令查看证书详情。

Q: 80 端口访问不通?

检查阿里云安全组是否放行了 80 端口,以及 Docker 容器端口映射是否正确。

Q: Docker 容器重启后网站无法访问?

确认 docker-compose.yml 中设置了 restart: always,确保证书和配置文件的挂载路径正确。

总结

通过 Docker 部署 Nginx + SSL 是一种可靠且易于维护的方案。Docker 的容器化隔离让环境管理更清爽,Nginx 的高性能和阿里云的免费证书则让 HTTPS 部署门槛几乎为零。这套方案适合个人博客、项目演示和小型 Web 应用的快速上线。