Skip to content

🚀 使用 Docker Compose 部署 Nginx 反向代理服务

🚀 使用 Docker Compose 部署 Nginx 反向代理服务

本文将详细介绍如何使用 Docker Compose 部署 Nginx 作为反向代理服务器,实现多端口、多后端服务的统一管理和负载分发。

📝 项目简介

Nginx 是一款轻量级的 Web 服务器/反向代理服务器电子邮件代理服务器,其特点是占有内存少,并发能力强。通过 Docker 容器化部署,可以快速搭建和管理 Nginx 服务。

核心特点:

  • 高性能:采用事件驱动架构,能够处理大量并发连接
  • 低资源占用:内存消耗少,适合资源受限环境
  • 反向代理:支持负载均衡和请求转发
  • 配置灵活:通过配置文件实现复杂路由规则
  • 静态文件服务:高效处理静态资源请求

🔧 部署前准备

系统环境要求

  • 操作系统:Linux、Windows、macOS
  • Docker 引擎:版本 20.10+
  • Docker Compose:版本 2.0+
  • 硬件资源
  • 内存:至少 512MB
  • 存储空间:至少 1GB 可用空间

环境检查

  1. 检查 Docker 服务状态 bash systemctl status docker 确保 Docker 服务处于 active (running) 状态

  2. 检查 Docker 版本 bash docker --version

  3. 创建部署目录

   mkdir -p /home/compose/nginx && cd /home/compose/nginx

⚙️ 配置 Docker Compose

准备配置文件

创建 docker-compose.yml 文件:

 services:
  nginx:
    restart: always    # 容器退出后自动重启(保障代理服务稳定)
    container_name: nginx  # 容器名称,便于管理(如查看日志、重启)
    image: nginx  # 官方 Nginx 镜像(默认 latest 版本,稳定可靠)
    privileged: true   # 特权模式:允许容器修改网络配置、访问宿主机资源(反向代理必需)

    ports:
      #- 444:444
      #- 443:443
      #- "81:80"

      # 集群1端口:3000-3006(主机端口=容器端口,简化配置)
      - 3000:3000
      - 3001:3001
      - 3002:3002
      - 3003:3003
      - 3004:3004
      - 3005:3005
      - 3006:3006

      # 集群2端口:5000-5005(跳过 5004)
      - 5000:5000
      - 5001:5001
      - 5002:5002
      - 5003:5003
      - 5005:5005

      # 集群3端口:7000-7001
      - 7000:7000
      - 7001:7001

      #- 9001:9001
    #network_mode: 'host'  # 注释:默认桥接模式,端口映射更灵活,host 模式无需端口映射但易冲突
    volumes:
      # 1. 静态文件目录:本地 ./html → 容器 /usr/share/nginx/html(默认静态页)
      - "./html:/usr/share/nginx/html"
      # 2. 自定义静态文件目录:本地 ./www → 容器 /var/www(可选,存放前端项目)
      - ./www:/var/www
      # 3. 日志目录:本地 ./logs → 容器 /var/log/nginx(访问日志、错误日志)
      - "./logs:/var/log/nginx"
      # 4. 主配置文件:本地 ./nginx.conf → 容器 /etc/nginx/nginx.conf(核心配置)
      - "./nginx.conf:/etc/nginx/nginx.conf"
      # 5. 证书目录:本地 ./cert → 容器 /etc/nginx/cert(启用 HTTPS 时使用)
      - ./cert:/etc/nginx/cert
      # 6. 虚拟主机配置:本地 ./conf.d → 容器 /etc/nginx/conf.d(反向代理规则)
      - ./conf.d:/etc/nginx/conf.d

      #/home/compose/nginx "./"当前目录下
      #容器内的配置不变动,只需要在容器映射yml文件这里修改一下,指向路径就好了。
      #- ./nginx:/etc/nginx
      #- /wwwroot:/wwwroot
    environment:
      #- NGINX_PORT=80
      - TZ=Asia/Shanghai  # 时区同步(确保日志时间与本地一致)
      #下面是搭建桥梁bridge而非host模式在这里不合适用。。。
      # 注释:默认使用桥接网络,无需额外定义 networks
    #networks:
      #- nginx_web
#networks:
  #nginx_web:
    #driver: bridge
# 注释:volumes 已通过目录挂载实现,无需额外定义
 #volumes:
  #data:

关键配置说明

  1. 镜像选择:使用官方 nginx 镜像
  2. 端口映射:将容器内多个端口映射到宿主机,支持不同服务访问
  3. 数据持久化
  4. ./html:/usr/share/nginx/html:静态网页目录
  5. ./logs:/var/log/nginx:日志目录
  6. ./nginx.conf:/etc/nginx/nginx.conf:主配置文件
  7. ./conf.d:/etc/nginx/conf.d:自定义配置目录
  8. 时区设置TZ=Asia/Shanghai 确保日志时间正确

🚀 启动与验证

启动服务

docker compose up -d

验证服务状态

  1. 检查容器运行状态 bash docker ps 应该看到 nginx 容器处于 Up 状态

  2. 查看服务日志 bash docker compose logs -f

  3. 测试端口连通性

   curl http://localhost:3000

🔌 基础配置与使用

Nginx 主配置

创建 nginx.conf 文件:


user  nginx;
worker_processes  auto;  # 自动适配 CPU 核心数,提升并发性能

error_log  /var/log/nginx/error.log notice;  # 错误日志路径与级别
pid        /var/run/nginx.pid;  # 进程 ID 存储路径


events {
    worker_connections  1024;  # 每个 worker 进程最大连接数,可根据需求调整为 51200   
}


http {
    include       /etc/nginx/mime.types;  # 加载 MIME 类型映射(如 .html 对应 text/html)
    default_type  application/octet-stream;  # 默认 MIME 类型(未知文件类型)

    # 日志格式定义(记录客户端 IP、请求方法、状态码等关键信息)
    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;  # 访问日志使用 main 格式

    sendfile        on;  # 启用零拷贝技术,提升文件传输效率
    #tcp_nopush     on;  # 开启后会累积数据再发送,适合大文件传输,默认关闭

    keepalive_timeout  65;  # 客户端连接超时时间(秒),避免连接频繁建立/关闭

    #gzip  on;  # 启用 Gzip 压缩,减少传输流量,需后端服务支持,默认关闭

    include /etc/nginx/conf.d/*.conf;  # 加载 conf.d 目录下的所有虚拟主机配置(核心!)
}

}

反向代理配置

conf.d/1.conf 中配置服务器集群:

示例:

# 集群1 - 指向 192.168.0.2
server {
    listen 3000;
    listen [::]:3000 ipv6only=on;
    charset utf-8;
    client_max_body_size 2G;

    location / {
        proxy_buffering off;
        proxy_buffer_size 128k;
        proxy_buffers 100 128k;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_pass http://192.168.0.2:3000;
    }
}

# 集群2 - 指向 192.168.0.10
server {
    listen 5000;
    charset utf-8;

    location / {
        proxy_buffer_size 64k;
        proxy_buffering on;
        proxy_buffers 4 64k;
        proxy_busy_buffers_size 64k;
        proxy_max_temp_file_size 1024m;
        proxy_redirect off;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_pass http://192.168.0.10:5000;
    }
}

# 集群3 - 指向 192.168.0.30
server {
    listen 7000;
    charset utf-8;

    location / {
        proxy_buffer_size 64k;
        proxy_buffering on;
        proxy_buffers 4 64k;
        proxy_busy_buffers_size 64k;
        proxy_max_temp_file_size 1024m;
        proxy_redirect off;
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_pass http://192.168.0.30:11434;
    }
}

完整:

# 集群1:转发到 192.168.0.2 服务器(3000-3006 端口)
server{
       listen 3000;
       listen [::]:3000 ipv6only=on;  # 支持 IPv6
       #server_name localhost docker.xieboke.net;
       charset utf-8;  # 启用 UTF-8 编码,避免中文乱码
    #Allow large attachments
    # 允许大文件上传(2G 上限,根据需求调整)
    client_max_body_size 2G; # 适当调整文件大小的上限
     #client_max_body_size 128M;
    #目录别名转发
    # 反向代理配置(核心:将 3000 端口请求转发到 192.168.0.2:3000)
    location  / {
    # 反向代理缓存配置(关闭缓存,适合实时服务;需缓存可改为 on)
    proxy_buffering off;
    proxy_buffer_size 128k;
    proxy_buffers 100 128k;

    # 支持 WebSocket 连接(升级 HTTP 协议)
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection keep-alive;
    #proxy_set_header Host $host; #这真是代理的好东西啊
    #proxy_set_header Host $http_host;
    # 传递请求头(让后端服务获取真实请求的 Host、IP)
    proxy_set_header Host $proxy_host; # 修改转发请求头,让8080端口的应用可以受到真实的请求
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_cache_bypass $http_upgrade;
    # 转发目标(需改为你的后端服务 IP:端口!)
    proxy_pass http://192.168.0.2:3000;
    }
    # 错误页面配置(500/502 等错误时显示 50x.html)
           error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }
    }

server{
       listen 3001;
       listen [::]:3001 ipv6only=on;
       charset utf-8;
    #Allow large attachments
    client_max_body_size 2G; # 适当调整文件大小的上限
    #目录别名转发
    location  / {
    # 缓存配置(启用缓存,提升静态资源访问速度)
    proxy_buffer_size 256k;
    proxy_buffering on;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;
    proxy_max_temp_file_size 2048m;
    proxy_redirect off;
    #proxy_set_header Host $host;#问题所在,没正确传递出httphost
    # 传递真实请求头
    proxy_set_header Host $http_host;
       #proxy_set_header X-Real-IP '192.168.0.19';#设置为nginx所在的ip地址
       #proxy_set_header X-Forwarded-Proto 'http';#从nginx访问的,只允许通过https,所以写死,不用$scheme了;
       #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;  # 仅缓存 GET/HEAD 请求
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;  # 缓存键定义
    proxy_pass http://192.168.0.2:3001/;  # 转发目标(需修改为你的后端)
    }
    }
# 省略 3002-3006、5000-5005 端口配置(与上述结构一致,核心修改 proxy_pass 目标)
server{
       listen 3002;
       listen [::]:3002 ipv6only=on;
       charset utf-8;
    #目录别名转发
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.2:3002/;
    }
    }
server{
       listen 3003;
       listen [::]:3003 ipv6only=on;
       charset utf-8;
    #目录别名转发
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.2:3003/;
    }
    }
server{
       listen 3004;
       listen [::]:3004 ipv6only=on;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.2:3004/;
    }
       #error_page  404              /404.html;

       # redirect server error pages to the static page /50x.html
       #
       #error_page   500 502 503 504  /50x.html;
       #location = /50x.html {
           #root   html;
       #}
    }
server{
       listen 3005;
       listen [::]:3005 ipv6only=on;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.2:3005/;
    }
    }
server{
       listen 3006;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.2:3006/;
    }
    }


#集群2
server{
       listen 5000;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.10:5000/;
    }
    }

server{
       listen 5001;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    proxy_set_header Host $host;
    #proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.10:5001/;
    }
    }

server{
       listen 5002;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    #proxy_pass http://192.168.0.10:5002/UI/Dashboard;
    proxy_pass http://192.168.0.10:5002/;
    }
    }

server{
       listen 5003;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.10:5003/;
    }
    }

server{
       listen 5005;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.10:5005/;
    }
}


#集群3
server{
       listen 7000;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    #proxy_set_header Host $http_host;
    proxy_set_header Host $proxy_host;
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.30:11434/;
    }
    }

# 集群3:7001 端口(支持跨域)
server{
       listen 7001;
       charset utf-8;
    location  / {
    proxy_buffer_size 64k;
    proxy_buffering on;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 64k;
    proxy_max_temp_file_size 1024m;
    proxy_redirect off;
    #proxy_set_header Host $host;
    #proxy_set_header Host $http_host;
    #proxy_set_header Host $proxy_host; # 修改转发请求头,让8080端口的应用可以受到真实的请求
    # 传递请求头(适配后端服务需求)
    proxy_set_header Host http://192.168.0.30:11434/api;
    #proxy_set_header Host http://192.168.0.19:7000/api; #堆上上面反代的ip还是回答Network Problem
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_cache_convert_head off;
    proxy_cache_methods GET HEAD;
    proxy_cache_key $scheme$request_method$proxy_host$request_uri;
    proxy_pass http://192.168.0.30:8080/;  # 转发目标(需修改)
    # CORS 跨域配置(允许前端跨域请求)
    add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token';
        if ($request_method = 'OPTIONS') {
            return 200;  # 处理 OPTIONS 预检请求
        }
    }
    }

配置优化建议

  1. 性能调优
  2. 根据 CPU 核心数设置 worker_processes
  3. 调整 worker_connections 提高并发处理能力

  4. 缓存配置

  5. 启用静态资源缓存
  6. 配置代理缓存减少后端压力

🛠️ 维护与管理

日常维护操作

  1. 服务启停 ```bash # 停止服务 docker compose down

# 启动服务 docker compose up -d

# 重启服务 docker compose restart ```

  1. 配置重载 bash # 进入容器重载配置 docker exec nginx nginx -s reload

  2. 数据备份 bash # 备份配置和日志 tar -czf nginx-backup-$(date +%Y%m%d).tar.gz ./conf.d ./nginx.conf ./logs

监控与日志

1.查看实时日志

   docker compose logs -f

2.访问日志分析

   tail -f logs/access.log

3.错误日志监控

   tail -f logs/error.log

🐛 常见问题排查

1. 端口冲突问题

问题现象:容器启动失败,提示地址已在使用中

解决方案

# 检查端口占用
netstat -tulpn | grep :3000

# 修改冲突端口或停止占用进程

2. 代理配置错误

问题现象:502 Bad Gateway 错误

解决方案: - 检查后端服务是否正常运行 - 验证 proxy_pass 地址是否正确 - 确认网络连通性

3. 权限问题

问题现象:配置文件加载失败

解决方案

# 确保挂载目录权限正确
chmod -R 755 ./conf.d
chmod 644 ./nginx.conf

4. 静态资源访问问题

问题现象:CSS/JS 文件加载失败

解决方案: - 检查 mime.types 包含 - 验证静态文件路径权限 - 确认 location 块配置正确

通过本教程,您应该已经成功部署并配置了 Nginx 反向代理服务。Nginx 的强大功能和灵活配置使其成为现代 Web 架构中的重要组件。如果在使用过程中遇到其他问题,可以参考 Nginx 官方文档或相关社区资源。