一、引言:需求背景与解决方案概述
在现代化Web开发中,企业或开发者常面临多项目部署需求:同一服务器需托管多个Web应用(如前端门户、后台管理系统、API服务等),且需通过不同二级域名(如api.example.com、admin.example.com)无端口号(默认80/443)访问,同时保障HTTPS安全传输。传统方案需配置多台服务器或复杂路由规则,而Docker+Nginx的组合提供了一种轻量、灵活且安全的解决方案。
本文将围绕以下核心目标展开:
- 使用Docker容器化部署多个Web项目;
- 通过Nginx反向代理实现二级域名路由;
- 配置HTTPS证书(Let’s Encrypt免费证书或自签名证书);
- 隐藏端口号,实现默认80/443端口访问;
- 优化性能与安全性。
二、环境准备与基础配置
1. 服务器与域名准备
- 服务器要求:Linux系统(Ubuntu/CentOS),已安装Docker与Docker Compose。
- 域名配置:主域名(如
example.com)需解析至服务器IP,二级域名(如api.example.com、admin.example.com)需配置CNAME或A记录指向主域名。
2. Docker基础环境搭建
# 安装Docker(Ubuntu示例)sudo apt updatesudo apt install docker.io docker-composesudo systemctl enable docker# 创建项目目录结构mkdir -p ~/web-projects/{project1,project2,nginx}cd ~/web-projects
3. Nginx容器基础配置
在nginx目录下创建docker-compose.yml与Nginx配置文件:
version: '3'services:nginx:image: nginx:latestcontainer_name: nginx-proxyports:- "80:80"- "443:443"volumes:- ./nginx/conf.d:/etc/nginx/conf.d- ./nginx/certs:/etc/nginx/certs- ./nginx/logs:/var/log/nginxrestart: unless-stopped
三、HTTPS证书配置
1. 使用Let’s Encrypt免费证书(推荐)
安装Certbot工具并获取证书:
# 安装Certbot(Ubuntu示例)sudo apt install certbot python3-certbot-nginx# 获取证书(需提前配置好域名解析)sudo certbot certonly --nginx -d api.example.com -d admin.example.com
证书将保存在/etc/letsencrypt/live/目录下,需手动复制到Nginx容器的/etc/nginx/certs卷中。
2. 自签名证书(测试环境)
生成自签名证书:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout ~/web-projects/nginx/certs/self.key \-out ~/web-projects/nginx/certs/self.crt \-subj "/CN=example.com"
在Nginx配置中引用此证书。
四、多Web项目Docker化部署
1. 示例项目1:Node.js应用
在project1目录下创建Dockerfile与app.js:
# project1/DockerfileFROM node:14WORKDIR /appCOPY package*.json ./RUN npm installCOPY . .EXPOSE 3000CMD ["node", "app.js"]
// project1/app.jsconst express = require('express');const app = express();app.get('/', (req, res) => res.send('Project 1'));app.listen(3000, () => console.log('Project 1 running on port 3000'));
构建并运行:
cd ~/web-projects/project1docker build -t project1 .docker run -d --name project1-app -p 3000:3000 project1
2. 示例项目2:Python Flask应用
类似地,在project2目录下部署Flask应用:
# project2/DockerfileFROM python:3.8WORKDIR /appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY . .EXPOSE 5000CMD ["python", "app.py"]
# project2/app.pyfrom flask import Flaskapp = Flask(__name__)@app.route('/')def home():return "Project 2"if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)
构建并运行:
cd ~/web-projects/project2docker build -t project2 .docker run -d --name project2-app -p 5000:5000 project2
五、Nginx反向代理与二级域名路由
在nginx/conf.d目录下创建proxy.conf:
# nginx/conf.d/proxy.confserver {listen 80;server_name api.example.com;return 301 https://$host$request_uri;}server {listen 443 ssl;server_name api.example.com;ssl_certificate /etc/nginx/certs/live/api.example.com/fullchain.pem;ssl_certificate_key /etc/nginx/certs/live/api.example.com/privkey.pem;location / {proxy_pass http://project1-app:3000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}server {listen 80;server_name admin.example.com;return 301 https://$host$request_uri;}server {listen 443 ssl;server_name admin.example.com;ssl_certificate /etc/nginx/certs/live/admin.example.com/fullchain.pem;ssl_certificate_key /etc/nginx/certs/live/admin.example.com/privkey.pem;location / {proxy_pass http://project2-app:5000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
关键点:
proxy_pass指向Docker容器名(需确保容器在同一Docker网络中);- HTTPS配置需引用证书路径;
- 强制HTTP转HTTPS(301重定向)。
六、Docker网络与容器互联
修改docker-compose.yml以加入Web项目容器:
version: '3'services:nginx:# ...(前文配置)networks:- webnetproject1-app:image: project1build: ./project1networks:- webnetproject2-app:image: project2build: ./project2networks:- webnetnetworks:webnet:driver: bridge
运行docker-compose up -d启动所有容器。
七、安全优化与性能调优
1. 安全配置
- 禁用SSLv3与弱加密套件:
ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256...';
- 启用HSTS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
2. 性能优化
- 启用Gzip压缩:
gzip on;gzip_types text/plain text/css application/json application/javascript text/xml;
- 配置缓存:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {expires 1y;add_header Cache-Control "public";}
八、常见问题与排查
- 502 Bad Gateway:检查目标容器是否运行,端口是否暴露。
- 证书无效:确认证书路径与域名匹配,或使用
openssl s_client -connect api.example.com:443测试。 - 容器互联失败:确保所有容器在同一Docker网络中。
九、总结与扩展
通过Docker与Nginx的组合,开发者可高效实现多Web项目的二级域名HTTPS无端口访问。此方案具有以下优势:
- 资源隔离:每个项目独立容器,避免冲突;
- 灵活扩展:新增项目仅需添加容器与Nginx配置;
- 安全可控:集中管理HTTPS证书与安全策略。
扩展建议:
- 结合CI/CD流水线自动化部署;
- 使用Traefik替代Nginx实现更动态的路由管理;
- 部署监控工具(如Prometheus+Grafana)实时观察容器状态。