docker nginx 和宿主机原生 nginx 服务的性能压测对比(附 nginx 配置优化思路)

结论先行

Docker 容器本身的性能开销只有约 7-8%,网上测试中观察到的巨大差距主要来自:

  1. 端口映射开销-p 8080:80 经过 NAT 转换,比 --network host 慢很多
  2. nginx 配置差异:默认镜像的 worker_connections、epoll、tcp_nodelay 等配置都较保守
  3. access_log 开销:高并发时日志写入成为瓶颈

当使用 host 网络模式 + 配置一致后,性能差距从 56% 缩小到 7-8%。


测试环境

  • 服务器:阿里云 ECS ecs.e-c1m1.large(2 vCPU 2 GiB)
  • 操作系统:Alibaba Cloud Linux 3.2104 LTS 64位
  • nginx 版本:1.20.1(宿主机 yum 安装 / Docker 官方镜像)
  • 压测工具:wrk(4 线程,1000 并发,持续 10 秒)

注意:ab 工具单线程无法打满 CPU,测试结果会偏低。更严格的测试应使用局域网内另一台机器发压。


测试一:默认配置对比(不公平对比)

宿主机 nginx(yum 安装默认配置)

 
bash
➜ wrk -t4 -c1000 -d10s http://localhost/
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    41.58ms   17.35ms 122.95ms   67.12%
    Req/Sec     5.74k     1.37k   11.04k    69.44%
Requests/sec:  22688.28

Docker nginx(端口映射模式)

 
bash
docker run -d -p 8080:80 nginx:1.20.1
➜ wrk -t4 -c1000 -d10s http://localhost:8080/
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    98.67ms   33.92ms 365.33ms   73.46%
    Req/Sec     2.53k   614.08     4.40k    73.15%
Requests/sec:   9928.93

表面结论:Docker 性能只有宿主机的 44%,差距 56%。

但这是不公平对比! 原因如下:

差异项宿主机Docker 默认
网络模式 本地直连 NAT 端口映射
worker_connections 4096 1024
use epoll
multi_accept ✅ on
tcp_nopush ✅ on 注释掉
tcp_nodelay ✅ on
worker_rlimit_nofile 65535

测试二:公平对比(host 网络 + 配置一致)

步骤 1:使用 host 网络模式

 
bash
docker run -d --name nginx --network host nginx:1.20.1

host 模式下容器直接使用宿主机网络栈,无 NAT 开销。

步骤 2:统一 nginx 配置

首先检查配置差异:

 
bash
# 宿主机配置
grep -E "worker_processes|worker_connections" /etc/nginx/nginx.conf

# Docker 配置
docker exec nginx cat /etc/nginx/nginx.conf | grep -E "worker_processes|worker_connections"

将宿主机配置复制到容器:

 
bash
docker cp /etc/nginx/nginx.conf nginx:/etc/nginx/nginx.conf
docker restart nginx

步骤 3:关闭 access_log(可选,消除 I/O 瓶颈)

 
bash
# 修改 nginx.conf
access_log off;

测试结果

环境网络模式配置access_logRequests/sec
宿主机 - 优化后 off ~39,000
Docker host 优化后 off ~36,500
Docker host 优化后 on ~30,000
Docker host 默认 on ~27,500
Docker 端口映射 默认 on ~9,900

真实结论:配置一致后,Docker 性能约为宿主机的 93%,真正的容器开销只有 7-8%


性能差距来源分析

1. 端口映射 vs host 网络(影响最大,约 30-40%)

-p 8080:80 模式下,每个请求都要经过 iptables NAT 转换:

 
客户端 → iptables DNAT → docker-proxy → 容器

--network host 模式下,容器直接监听宿主机端口,无额外开销。

2. nginx 配置差异(影响约 20-30%)

Docker 官方 nginx 镜像使用保守的默认配置,主要差异:

  • worker_connections 1024:高并发时成为瓶颈
  • 缺少 use epoll:未使用 Linux 高效 I/O 多路复用
  • 缺少 multi_accept on:每次只 accept 一个连接
  • 缺少 tcp_nopush/tcp_nodelay:网络传输未优化

3. access_log 开销(影响约 15-20%)

高并发时,每个请求都要写日志,磁盘 I/O 成为瓶颈。关闭或使用 buffer 模式可显著提升性能。

4. 容器运行时开销(约 7-8%)

排除以上因素后,剩余的性能差距来自:

  • namespace 隔离
  • overlay 文件系统
  • cgroup 资源统计

nginx 性能优化配置

 
nginx
# ===== 进程层面 =====
worker_processes auto;           # worker 数,通常设为 CPU 核心数
worker_rlimit_nofile 65535;      # worker 能打开的文件描述符上限

# ===== 事件层面 =====
events {
    worker_connections 4096;     # 单个 worker 最大连接数
    use epoll;                   # Linux 用 epoll,高效 I/O 多路复用
    multi_accept on;             # 一次 accept 多个连接
}

# ===== HTTP 层面 =====
http {
    # 文件传输优化
    sendfile on;                 # 零拷贝发送文件
    tcp_nopush on;               # 攒一波再发(配合 sendfile)
    tcp_nodelay on;              # 小包立即发(keepalive 连接时)

    # 连接复用
    keepalive_timeout 65;        # 长连接超时
    keepalive_requests 1000;     # 单个长连接最多处理请求数

    # 缓冲区
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;

    # Gzip 压缩(CPU 换带宽)
    gzip on;
    gzip_comp_level 2;
    gzip_types text/plain text/css application/json application/javascript;

    # 日志优化(高并发时影响大)
    access_log off;              # 或用 buffer
    # access_log /var/log/nginx/access.log main buffer=32k flush=5s;
}

优化优先级

优先级配置项解决什么问题
1 worker_processes 没用满 CPU 核心
2 worker_rlimit_nofile 文件描述符不够
3 worker_connections 连接数不够
4 sendfile + tcp_nopush 静态文件传输慢
5 keepalive 频繁建立连接开销大
6 access_log off/buffer 磁盘 I/O 成为瓶颈
7 gzip 带宽不够(用 CPU 换)

Docker 部署最佳实践

如果追求极致性能:

 
bash
docker run -d \
  --name nginx \
  --network host \
  --ulimit nofile=65535:65535 \
  -v /path/to/optimized/nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:1.20.1

关键点:

  • --network host:避免 NAT 开销
  • --ulimit nofile=65535:65535:提高文件描述符限制
  • 挂载优化后的配置文件

总结

常见误解实际情况
Docker 性能损失 50%+ 真正的容器开销只有 7-8%
容器不适合高性能场景 配置正确的话完全可以
端口映射很方便 高并发场景建议用 host 网络

核心结论:性能问题大多来自配置差异,而非容器本身。公平对比时,Docker 的性能损失在可接受范围内。


测试日期:2025年11月

posted @ 2025-11-20 22:56  猫哥_kaiye  阅读(37)  评论(0)    收藏  举报