Docker + Nginx 反向代理完整解决方案

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
# 部署Web服务
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-image

# API服务
docker run -d --name api -p 127.0.0.1:4000:4000 api-image

# 数据库
docker 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
# /etc/nginx/nginx.conf
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
# /etc/nginx/conf.d/app.conf
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优化
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

# 生产环境crontab
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

# Docker环境特殊处理
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
  1. 网络层防护

    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
  2. 应用层防护

    nginx

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # IP白名单
    location /admin {
    allow 192.168.1.0/24;
    deny all;
    }

    # 基础认证
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;

    # HTTP方法限制
    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
# 统计HTTP状态码
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

# 检查DNS解析
dig +short app.example.com

# 完整HTTPS握手测试
openssl 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}}'"
  1. 资源使用监控

    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
  2. 服务健康检查

    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
# /etc/logrotate.d/nginx
/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"
  1. 变更流程

    markdown

    1
    2
    3
    - 修改前: `nginx -t`
    - 提交前: `git diff`
    - 部署后: `nginx -s reload`
  2. 环境分离

    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压缩
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 365d;
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文件使用,包含:

  1. 完整的配置方案和命令
  2. 可直接复用的代码块
  3. 可视化流程图
  4. 详细的参数解释
  5. 故障排查指南
  6. 监控维护策略
  7. 最佳实践建议

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
# Web应用
docker run -d --name web-app -p 127.0.0.1:3000:3000 your-web-image

# API服务
docker run -d --name api-service -p 127.0.0.1:4000:4000 your-api-image

# 管理后台
docker run -d --name admin-panel -p 127.0.0.1:5000:80 your-admin-image

# 静态资源
docker 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压缩
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;

# ============== 服务配置 ==============

# 主Web应用
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";
}
}

# API服务
server {
listen 80;
server_name api.yourdomain.com;

location / {
proxy_pass http://127.0.0.1:4000;

# CORS支持
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;
}
}

# API文档
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;

# IP限制
allow 192.168.1.0/24; # 内网IP段
allow 203.0.113.45; # 特定公网IP
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
# 进入Nginx容器
docker exec -it nginx-proxy sh

# 安装Certbot
apk add certbot certbot-nginx

# 申请证书(替换为您的域名)
certbot --nginx -d app.yourdomain.com -d api.yourdomain.com -d admin.yourdomain.com -d static.yourdomain.com

# 设置自动续期
echo "0 0 * * * certbot renew --quiet" >> /etc/crontabs/root

关键配置说明

  1. 端口绑定安全:

    bash

    1
    2
    # 所有容器只绑定到127.0.0.1,防止外部直接访问
    -p 127.0.0.1:3000:3000
  2. 服务隔离:

    • 每个服务通过不同子域名区分
    • 默认服务器块拒绝非法请求
  3. 性能优化:

    • 启用Gzip压缩
    • 静态资源设置长期缓存
    • 合理的超时设置
  4. 安全措施:

    • 管理后台IP限制
    • API文档基础认证
    • 静态资源禁止执行PHP

维护建议

  1. 配置验证:

    bash

    1
    docker exec nginx-proxy nginx -t
  2. 重载配置:

    bash

    1
    docker exec nginx-proxy nginx -s reload
  3. 日志查看:

    bash

    1
    docker exec nginx-proxy tail -f /var/log/nginx/access.log
  4. 备份配置:

    bash

    1
    docker cp nginx-proxy:/etc/nginx/nginx.conf ./nginx-backup.conf

这个方案提供了完整的单文件配置,适合在单个服务器上管理多个Docker容器服务,通过Nginx实现统一入口和反向代理功能。


Docker + Nginx 反向代理完整解决方案
https://lz107488.github.io/ixiaoze/2025/07/22/Docker + Nginx 反向代理完整解决方案/
发布于
2025年7月22日
许可协议