Docker与Nginx实战:HTTPS二级域名无端口访问多Web项目指南

一、引言:需求背景与解决方案概述

在现代化Web开发中,企业或开发者常面临多项目部署需求:同一服务器需托管多个Web应用(如前端门户、后台管理系统、API服务等),且需通过不同二级域名(如api.example.comadmin.example.com)无端口号(默认80/443)访问,同时保障HTTPS安全传输。传统方案需配置多台服务器或复杂路由规则,而Docker+Nginx的组合提供了一种轻量、灵活且安全的解决方案。

本文将围绕以下核心目标展开:

  1. 使用Docker容器化部署多个Web项目;
  2. 通过Nginx反向代理实现二级域名路由;
  3. 配置HTTPS证书(Let’s Encrypt免费证书或自签名证书);
  4. 隐藏端口号,实现默认80/443端口访问;
  5. 优化性能与安全性。

二、环境准备与基础配置

1. 服务器与域名准备

  • 服务器要求:Linux系统(Ubuntu/CentOS),已安装Docker与Docker Compose。
  • 域名配置:主域名(如example.com)需解析至服务器IP,二级域名(如api.example.comadmin.example.com)需配置CNAME或A记录指向主域名。

2. Docker基础环境搭建

  1. # 安装Docker(Ubuntu示例)
  2. sudo apt update
  3. sudo apt install docker.io docker-compose
  4. sudo systemctl enable docker
  5. # 创建项目目录结构
  6. mkdir -p ~/web-projects/{project1,project2,nginx}
  7. cd ~/web-projects

3. Nginx容器基础配置

nginx目录下创建docker-compose.yml与Nginx配置文件:

  1. version: '3'
  2. services:
  3. nginx:
  4. image: nginx:latest
  5. container_name: nginx-proxy
  6. ports:
  7. - "80:80"
  8. - "443:443"
  9. volumes:
  10. - ./nginx/conf.d:/etc/nginx/conf.d
  11. - ./nginx/certs:/etc/nginx/certs
  12. - ./nginx/logs:/var/log/nginx
  13. restart: unless-stopped

三、HTTPS证书配置

1. 使用Let’s Encrypt免费证书(推荐)

安装Certbot工具并获取证书:

  1. # 安装Certbot(Ubuntu示例)
  2. sudo apt install certbot python3-certbot-nginx
  3. # 获取证书(需提前配置好域名解析)
  4. sudo certbot certonly --nginx -d api.example.com -d admin.example.com

证书将保存在/etc/letsencrypt/live/目录下,需手动复制到Nginx容器的/etc/nginx/certs卷中。

2. 自签名证书(测试环境)

生成自签名证书:

  1. openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  2. -keyout ~/web-projects/nginx/certs/self.key \
  3. -out ~/web-projects/nginx/certs/self.crt \
  4. -subj "/CN=example.com"

在Nginx配置中引用此证书。

四、多Web项目Docker化部署

1. 示例项目1:Node.js应用

project1目录下创建Dockerfileapp.js

  1. # project1/Dockerfile
  2. FROM node:14
  3. WORKDIR /app
  4. COPY package*.json ./
  5. RUN npm install
  6. COPY . .
  7. EXPOSE 3000
  8. CMD ["node", "app.js"]
  1. // project1/app.js
  2. const express = require('express');
  3. const app = express();
  4. app.get('/', (req, res) => res.send('Project 1'));
  5. app.listen(3000, () => console.log('Project 1 running on port 3000'));

构建并运行:

  1. cd ~/web-projects/project1
  2. docker build -t project1 .
  3. docker run -d --name project1-app -p 3000:3000 project1

2. 示例项目2:Python Flask应用

类似地,在project2目录下部署Flask应用:

  1. # project2/Dockerfile
  2. FROM python:3.8
  3. WORKDIR /app
  4. COPY requirements.txt .
  5. RUN pip install -r requirements.txt
  6. COPY . .
  7. EXPOSE 5000
  8. CMD ["python", "app.py"]
  1. # project2/app.py
  2. from flask import Flask
  3. app = Flask(__name__)
  4. @app.route('/')
  5. def home():
  6. return "Project 2"
  7. if __name__ == '__main__':
  8. app.run(host='0.0.0.0', port=5000)

构建并运行:

  1. cd ~/web-projects/project2
  2. docker build -t project2 .
  3. docker run -d --name project2-app -p 5000:5000 project2

五、Nginx反向代理与二级域名路由

nginx/conf.d目录下创建proxy.conf

  1. # nginx/conf.d/proxy.conf
  2. server {
  3. listen 80;
  4. server_name api.example.com;
  5. return 301 https://$host$request_uri;
  6. }
  7. server {
  8. listen 443 ssl;
  9. server_name api.example.com;
  10. ssl_certificate /etc/nginx/certs/live/api.example.com/fullchain.pem;
  11. ssl_certificate_key /etc/nginx/certs/live/api.example.com/privkey.pem;
  12. location / {
  13. proxy_pass http://project1-app:3000;
  14. proxy_set_header Host $host;
  15. proxy_set_header X-Real-IP $remote_addr;
  16. }
  17. }
  18. server {
  19. listen 80;
  20. server_name admin.example.com;
  21. return 301 https://$host$request_uri;
  22. }
  23. server {
  24. listen 443 ssl;
  25. server_name admin.example.com;
  26. ssl_certificate /etc/nginx/certs/live/admin.example.com/fullchain.pem;
  27. ssl_certificate_key /etc/nginx/certs/live/admin.example.com/privkey.pem;
  28. location / {
  29. proxy_pass http://project2-app:5000;
  30. proxy_set_header Host $host;
  31. proxy_set_header X-Real-IP $remote_addr;
  32. }
  33. }

关键点

  • proxy_pass指向Docker容器名(需确保容器在同一Docker网络中);
  • HTTPS配置需引用证书路径;
  • 强制HTTP转HTTPS(301重定向)。

六、Docker网络与容器互联

修改docker-compose.yml以加入Web项目容器:

  1. version: '3'
  2. services:
  3. nginx:
  4. # ...(前文配置)
  5. networks:
  6. - webnet
  7. project1-app:
  8. image: project1
  9. build: ./project1
  10. networks:
  11. - webnet
  12. project2-app:
  13. image: project2
  14. build: ./project2
  15. networks:
  16. - webnet
  17. networks:
  18. webnet:
  19. driver: bridge

运行docker-compose up -d启动所有容器。

七、安全优化与性能调优

1. 安全配置

  • 禁用SSLv3与弱加密套件:
    1. ssl_protocols TLSv1.2 TLSv1.3;
    2. ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256...';
  • 启用HSTS:
    1. add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

2. 性能优化

  • 启用Gzip压缩:
    1. gzip on;
    2. gzip_types text/plain text/css application/json application/javascript text/xml;
  • 配置缓存:
    1. location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    2. expires 1y;
    3. add_header Cache-Control "public";
    4. }

八、常见问题与排查

  1. 502 Bad Gateway:检查目标容器是否运行,端口是否暴露。
  2. 证书无效:确认证书路径与域名匹配,或使用openssl s_client -connect api.example.com:443测试。
  3. 容器互联失败:确保所有容器在同一Docker网络中。

九、总结与扩展

通过Docker与Nginx的组合,开发者可高效实现多Web项目的二级域名HTTPS无端口访问。此方案具有以下优势:

  • 资源隔离:每个项目独立容器,避免冲突;
  • 灵活扩展:新增项目仅需添加容器与Nginx配置;
  • 安全可控:集中管理HTTPS证书与安全策略。

扩展建议

  • 结合CI/CD流水线自动化部署;
  • 使用Traefik替代Nginx实现更动态的路由管理;
  • 部署监控工具(如Prometheus+Grafana)实时观察容器状态。