Docker + Nginx 反向代理完整解决方案 目录
架构设计
容器部署
Nginx配置
Certbot自动化
安全加固
故障排查
监控维护
最佳实践
工作流程
附录
知识库
架构设计 网络拓扑图 graph TD
A[客户端] --> B[80/443]
B --> C[Nginx反向代理]
C --> D[容器A:3000]
C --> E[容器B:4000]
C --> F[容器C:5000]
style C fill:#4CAF50,stroke:#388E3C
设计原则
原则
实现方式
重要性
最小权限
-p 127.0.0.1:3000:3000
🔥🔥🔥
单点入口
只开放80/443端口
🔥🔥🔥
配置隔离
分服务配置
🔥🔥
容器部署 标准部署流程 bash
1 2 3 4 5 6 7 docker run -d --name web-app \ -p 127.0 .0.1 :3000 :3000 \ -v /path/to /data:/app/data \ -e "ENV=production" \ --memory="512m" \ your-image:tag
关键参数解析 markdown
1 2 3 4 5 6 7 1. `-p 127.0.0.1:3000:3000` - 只允许本地访问 - 防止端口暴露2. `--memory="512m"` - 限制内存用量 - 防止OOM攻击
多容器部署示例 bash
1 2 3 4 5 6 7 8 docker run -d --name app -p 127.0.0.1:3000 :3000 app-imagedocker run -d --name api -p 127.0.0.1:4000 :4000 api-imagedocker run -d --name db -p 127.0.0.1:5432 :5432 postgres
Nginx配置 核心配置结构 nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 user www-data;worker_processes auto;events { worker_connections 1024 ; }http { add_header X-Frame-Options "DENY" ; add_header Content-Security-Policy "default-src 'self'" ; proxy_http_version 1 .1 ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; include /etc/nginx/conf.d/*.conf ; }
HTTPS服务模板 nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 server { listen 80 ; server_name app.example.com; return 301 https://$host $request_uri ; }server { listen 443 ssl http2; server_name app.example.com; ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3 ; ssl_prefer_server_ciphers on ; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256' ; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1 .1 ; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection "upgrade" ; } }
WebSocket支持 nginx
1 2 3 4 5 6 location /ws { proxy_pass http://127.0.0.1:4000; proxy_http_version 1 .1 ; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection "upgrade" ; }
Certbot自动化 证书申请流程 bash
1 2 3 4 5 6 7 8 sudo certbot --nginx -d example.com sudo certbot --nginx -d example.com -d api.example.com sudo certbot certonly --manual --preferred-challenges=dns -d *.example.com
自动续期方案 bash
1 2 3 4 5 6 7 8 sudo certbot renew --dry-run 0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx" docker exec nginx sh -c 'certbot renew --webroot -w /var/www/certbot '
证书期限与限制
项目
详情
默认有效期
90天
续期时间窗口
到期前30天
续期间隔限制
每60小时最多5次
最大续期失败次数
每周每域名5次
常见续期错误处理 bash
1 2 3 4 5 6 7 8 sudo chmod 644 /etc/letsencrypt/renewal/ *.conf certbot renew --pre-hook "docker stop nginx" --post-hook "docker start nginx" certbot renew --force-renewal
安全加固 三级防护体系 markdown
1 2 3 4 5 6 7 8 9 10 1. **容器层安全** ```bash # 只读文件系统 docker run --read-only # 禁止权限提升 docker run --security-opt ="no-new-privileges" # 用户命名空间隔离 docker run --userns =host
网络层防护
bash
1 2 3 4 5 6 sudo ufw default deny incoming sudo ufw allow 443 /tcp sudo iptables -I DOCKER-USER -i docker0 ! -o docker0 -j DROP
应用层防护
nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 location /admin { allow 192.168.1.0 /24 ; deny all; }auth_basic "Restricted Area" ;auth_basic_user_file /etc/nginx/.htpasswd;if ($request_method !~ ^(GET|POST)$) { return 405 ; }
text
1 2 3 4 5 6 ### 安全头增强 ```nginx add_header Strict -Transport-Security "max-age=31536000; includeSubDomains" always ; add_header X-Content-Type -Options "nosniff" always ; add_header X-XSS-Protection "1; mode=block" always ; add_header Referrer-Policy "strict-origin-when-cross-origin" always ;
故障排查 快速诊断表
症状
检查命令
解决方案
502错误
curl -v http://127.0.0.1:3000
重启容器
SSL过期
sudo certbot certificates
强制续期
性能差
docker stats
调整资源限制
配置错误
docker exec nginx nginx -t
修复配置文件
端口冲突
`ss -tulnp
grep 443`
停止占用进程
日志分析技巧 bash
1 2 3 4 5 6 7 8 cat /var/ log/nginx/ access.log | awk '{print $9}' | sort | uniq -c tail -f /var/ log/nginx/ error.log grep "upstream timed out" /var/ log/nginx/ error.log
网络诊断工具 bash
1 2 3 4 5 6 7 8 nc -zv 127.0.0.1 3000 dig +short app.example.comopenssl s_client -connect app.example.com:443 -servername app.example.com
监控维护 健康检查方案 markdown
1 2 3 1. **容器状态监控** ```bash watch -n 5 "docker ps --format 'table {{.Names }} \t {{.Status }} \t {{.Ports }} '"
资源使用监控
bash
1 2 3 4 5 6 7 while true ; do docker stats --no -stream --format \ "{{.Name}}: {{.MemUsage}} | {{.CPUPerc}}" | \ ts '[%Y-%m-%d %H:%M:%S]' >> /var /log/container_stats.log sleep 60 done
服务健康检查
bash
1 2 docker run --restart =on-failure:5 your-image
text
1 2 3 4 5 ### 备份策略`` `markdown - **每日配置备份** ` `` bash 0 2 * * * tar -czvf /backup/nginx_$(date +\%Y\%m\%d).tar.gz /etc/nginx
证书备份
bash
1 0 1 * * * rsync -avz /etc/letsencrypt backup-server:/ssl-backups
数据库备份
bash
1 0 3 * * * docker exec db pg_dump -U postgres mydb > /backup/db_$(date +\%Y\%m\%d).sql
text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ```bash/var/ log/nginx/ *.log { daily missingok rotate 30 compress delaycompress notifempty create 0640 www-data adm sharedscripts postrotate docker exec nginx nginx -s reload endscript }
最佳实践 配置管理 markdown
1 2 3 4 5 6 7 1 . **版本控制** ```bash # 初始化Git仓库 cd /etc/nginx git init git add nginx.conf conf .d/ git commit -m "Initial config"
变更流程
markdown
1 2 3 - 修改前: `nginx -t` - 提交前: `git diff` - 部署后: `nginx -s reload`
环境分离
markdown
1 2 3 - 开发环境: 使用自签名证书- 测试环境: 使用staging证书- 生产环境: 正式证书
text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ```nginx gzip on ; gzip_types text /plain text /css application /json application /javascript; upstream backend { server 127.0 .0 .1 :3000 ; keepalive 32 ; } location ~* \.(js|css|png|jpg)$ { expires 365 d; add_header Cache-Control "public, immutable" ; }
定期维护 bash
1 2 3 4 5 6 7 8 9 10 11 docker system prune -af docker pull nginx:latest docker scan your-image:tag # 证书到期提醒 echo "0 8 * * * openssl x509 -enddate -noout -in /path/to/cert.pem | mail -s 'Cert Expiry' admin@example.com" | crontab -
工作流程 部署流程图 graph LR
A[启动容器] --> B[配置Nginx]
B --> C[申请SSL证书]
C --> D[设置自动续期]
D --> E[安全加固]
E --> F[监控维护]
style A fill:#FFEB3B,stroke:#FBC02D
style F fill:#4CAF50,stroke:#388E3C
更新流程 sequenceDiagram
participant 管理员
participant Git
participant 服务器
participant Docker
管理员->>Git: 提交配置变更
Git->>服务器: 触发CI/CD
服务器->>服务器: 测试配置(nginx -t)
服务器->>Docker: 重载Nginx(nginx -s reload)
Docker-->>服务器: 返回结果
服务器-->>管理员: 通知部署状态
附录 Docker命令速查
功能
命令
查看运行容器
docker ps
查看容器日志
docker logs -f 容器名
进入容器
docker exec -it 容器名 sh
构建镜像
docker build -t 镜像名 .
清理资源
docker system prune -af
Nginx命令速查
功能
命令
测试配置
nginx -t
重载配置
nginx -s reload
查看版本
nginx -v
检查端口
`ss -tulnp
grep nginx`
Certbot命令速查
功能
命令
申请证书
certbot --nginx -d 域名
续期测试
certbot renew --dry-run
查看证书
certbot certificates
删除证书
certbot delete --cert-name 域名
系统工具速查
功能
命令
端口扫描
nmap -sT 127.0.0.1
连接测试
telnet 127.0.0.1 端口
进程监控
htop
网络监控
iftop -i eth0
知识库 Docker网络模型 markdown
1 2 3 4 5 6 7 8 9 10 11 12 1. **Bridge模式** - 默认网络模式 - 容器获得独立IP - 通过docker0网桥通信2. **Host模式** - 容器共享主机网络栈 - 性能更好,安全性较低3. **Overlay网络** - 多主机容器通信 - 适用于Swarm/K8s集群
HTTPS工作原理 markdown
1 2 3 4 5 6 7 8 9 10 11 12 13 1. **握手过程** - ClientHello: 客户端支持的协议/密码套件 - ServerHello: 服务器选择的协议/证书 - 密钥交换: 建立加密通道2. **证书验证** - 检查证书链 - 验证域名匹配 - 检查有效期3. **会话恢复** - Session ID: 传统恢复方式 - Session Tickets: 无状态恢复
Nginx处理流程 graph TD
A[客户端请求] --> B[Nginx接收]
B --> C{匹配Server块}
C -->|匹配| D[处理Location]
C -->|不匹配| E[默认Server]
D --> F[代理到后端]
F --> G[返回响应]
E --> H[返回错误]
终极提示 : 定期进行安全审计和压力测试,确保系统在高负载和攻击场景下的稳定性
此完整Markdown文档可以直接保存为.md文件使用,包含:
完整的配置方案和命令
可直接复用的代码块
可视化流程图
详细的参数解释
故障排查指南
监控维护策略
最佳实践建议
2. 单服务器多容器反向代理配置方案 以下是一个完整的单文件 Nginx 配置方案,适用于在单个服务器上通过 Docker 运行多个容器服务,并通过 Nginx 反向代理统一暴露。
完整配置方案 1. 首先准备 Docker 容器 假设您有以下容器服务运行在同一台服务器上:
Web 应用 (Node.js): 映射到宿主机 3000 端口
API 服务 (Python): 映射到宿主机 4000 端口
管理后台 (PHP): 映射到宿主机 5000 端口
静态资源 (Nginx): 映射到宿主机 6000 端口
启动命令示例:
bash
1 2 3 4 5 6 7 8 9 10 11 docker run -d --name web-app -p 127.0.0.1:3000 :3000 your-web-imagedocker run -d --name api-service -p 127.0.0.1:4000 :4000 your-api-imagedocker run -d --name admin-panel -p 127.0.0.1:5000 :80 your-admin-imagedocker run -d --name static-assets -p 127.0.0.1:6000 :80 nginx:alpine
2. 创建完整的 Nginx 配置文件 将以下内容保存为 /etc/nginx/nginx.conf:
nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 user www-data;worker_processes auto;pid /run/nginx.pid;events { worker_connections 1024 ; }http { include mime.types; default_type application/octet-stream; sendfile on ; keepalive_timeout 65 ; log_format main '$remote_addr - $remote_user [$time_local ] "$request " ' '$status $body_bytes_sent "$http_referer " ' '"$http_user_agent " "$http_x_forwarded_for "' ; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error .log warn ; gzip on ; gzip_types text/plain text/css application/json application/javascript text/xml; proxy_http_version 1 .1 ; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection 'upgrade' ; proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; server { listen 80 ; server_name app.yourdomain.com; location / { proxy_pass http://127.0.0.1:3000; proxy_connect_timeout 60s ; proxy_read_timeout 600s ; proxy_send_timeout 600s ; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { proxy_pass http://127.0.0.1:3000; expires 30d ; add_header Cache-Control "public" ; } } server { listen 80 ; server_name api.yourdomain.com; location / { proxy_pass http://127.0.0.1:4000; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type' always; if ($request_method = 'OPTIONS' ) { return 204 ; } } location /docs { proxy_pass http://127.0.0.1:4000/docs; auth_basic "API Documentation" ; auth_basic_user_file /etc/nginx/.htpasswd; } } server { listen 80 ; server_name admin.yourdomain.com; location / { proxy_pass http://127.0.0.1:5000; allow 192.168.1.0 /24 ; allow 203.0.113.45 ; deny all; auth_basic "Admin Area" ; auth_basic_user_file /etc/nginx/.htpasswd; } } server { listen 80 ; server_name static.yourdomain.com; location / { proxy_pass http://127.0.0.1:6000; expires 1y ; add_header Cache-Control "public, immutable" ; } } server { listen 80 default_server; server_name _; return 444 ; } }
3. 启动 Nginx 容器 bash
1 2 3 4 5 6 7 docker run -d --name nginx-proxy \ -p 80 :80 \ -p 443 :443 \ -v /etc/ nginx/nginx.conf:/ etc/nginx/ nginx.conf:ro \ -v /etc/ nginx/.htpasswd:/ etc/nginx/ .htpasswd:ro \ -v /var/ log/nginx:/ var/log/ nginx \ nginx:alpine
4. 可选:配置 HTTPS 使用 Let’s Encrypt 自动获取证书:
bash
1 2 3 4 5 6 7 8 9 10 11 docker exec -it nginx-proxy sh apk add certbot certbot-nginx certbot --nginx -d app.yourdomain.com -d api.yourdomain.com -d admin.yourdomain.com -d static.yourdomain.comecho "0 0 * * * certbot renew --quiet" >> /etc/crontabs/root
关键配置说明
端口绑定安全 :
bash
1 2 # 所有容器只绑定到127.0.0.1 ,防止外部直接访问 -p 127.0.0.1 :3000:3000
服务隔离 :
每个服务通过不同子域名区分
默认服务器块拒绝非法请求
性能优化 :
启用Gzip压缩
静态资源设置长期缓存
合理的超时设置
安全措施 :
管理后台IP限制
API文档基础认证
静态资源禁止执行PHP
维护建议
配置验证 :
bash
1 docker exec nginx-proxy nginx -t
重载配置 :
bash
1 docker exec nginx-proxy nginx -s reload
日志查看 :
bash
1 docker exec nginx-proxy tail -f /var/ log/nginx/ access.log
备份配置 :
bash
1 docker cp nginx-proxy:/etc/ nginx/nginx.conf ./ nginx-backup.conf
这个方案提供了完整的单文件配置,适合在单个服务器上管理多个Docker容器服务,通过Nginx实现统一入口和反向代理功能。