当前位置: 首页 > article >正文

使用 Docker 和 Nginx 实现反向代理:统一端口路由多服务的完整指南

场景需求

假设我们有一个 Spring Boot 应用(app.jar),需要启动多个实例,分别运行在 80808081 端口,并通过 Nginx 反向代理实现以下功能:

  • 外部通过 80 统一端口访问服务。
  • 根据 URL 路径前缀转发到不同端口的服务:
    • 请求 /service1/xxx 转发到 8080 端口。
    • 请求 /service2/xxx 转发到 8081 端口。

准备工作

  1. 安装 Docker 和 Docker Compose(官方安装文档)。
  2. 将 app.jar 文件放置在工作目录中(例如 ~/projects/myapp)。
  3. 确保 app.jar 在启动时可接受外部请求(如配置 server.port=8080)。

步骤 1:创建 Docker 网络

为了提高容器间通信的安全性,创建一个自定义网络:

<BASH>

docker network create nginx-proxy-network

步骤 2:编写服务镜像的 Dockerfile

创建文件 Dockerfile,内容如下:

<DOCKERFILE>

FROM openjdk:17-alpine

# 复制 jar 包到容器内
COPY app.jar /app/app.jar

# 暴露端口(实际端口通过启动命令指定)
EXPOSE ${PORT}

# 启动命令,通过环境变量指定端口和配置文件
CMD ["sh", "-c", "java -jar /app/app.jar --server.port=${PORT} --spring.profiles.active=${PROFILE}"]

步骤 3:启动多个服务容器

启动两个服务实例,分别映射到宿主机的 80808081 端口:

<BASH>

# 构建镜像
docker build -t myapp-service .

# 启动服务实例1(端口 8080)
docker run -d --name service1 \
  -e PORT=8080 \
  -e PROFILE=dev \
  --network nginx-proxy-network \
  -p 8080:8080 \
  myapp-service

# 启动服务实例2(端口 8081)
docker run -d --name service2 \
  -e PORT=8081 \
  -e PROFILE=test \
  --network nginx-proxy-network \
  -p 8081:8081 \
  myapp-service

步骤 4:编写 Nginx 配置文件

创建文件 nginx.conf,配置路由规则:

<NGINX>

events {
    worker_connections  1024;
}

http {
    server {
        listen 80;
        server_name localhost;

        # 路由到 service1(端口 8080)
        location /service1/ {
            proxy_pass http://service1:8080/;  # 使用 Docker 容器名直接访问
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 路由到 service2(端口 8081)
        location /service2/ {
            proxy_pass http://service2:8081/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

步骤 5:启动 Nginx 容器

<BASH>

docker run -d --name nginx-proxy \
  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \
  --network nginx-proxy-network \
  -p 80:80 \
  nginx:alpine

步骤 6:测试验证

发起请求测试路由是否正确:

<BASH>

# 访问 service1
curl http://localhost/service1/hello

# 访问 service2
curl http://localhost/service2/hello

核心原理

  1. Docker 网络:所有容器加入同一网络,通过容器名(如 service1)直接通信,无需暴露外网端口。
  2. Nginx 代理
    • location /service1/ 匹配以 /service1/ 开头的请求。
    • proxy_pass 将请求转发到对应容器的内部端口。
  3. 解耦访问入口:前端只需调用 80 端口,后端服务的真实端口对外隐藏。

配置优化建议

1. 静态资源与动态请求分离

<NGINX>

location /static/ {
    root /var/www/html;
    expires 30d;
}

location /api/ {
    proxy_pass http://backend;
}
2. 负载均衡

若单个服务需多实例,可配置负载均衡:

<NGINX>

upstream backend {
    server service1:8080;
    server service2:8081;
}

location / {
    proxy_pass http://backend;
}
3. 健康检查

在服务容器中添加健康检查端点:

<DOCKERFILE>

HEALTHCHECK --interval=30s --timeout=10s \
  CMD curl -f http://localhost:${PORT}/actuator/health || exit 1

完整架构图

                              +----------------+
                              |    Frontend    |
                              +----------------+
                                      |
                                      | 80 端口
                                      v
+----------------+            +----------------+            +----------------+
|   Nginx Proxy  | --service1->|  Service1:8080 |            |  Service2:8081 |
|   (Docker)     | --service2->|  (Docker)      |            |  (Docker)      |
+----------------+            +----------------+            +----------------+

常见问题排查

  1. Nginx 返回 502 Bad Gateway
    • 检查服务容器是否运行正常:docker logs service1
    • 确认 Nginx 配置中的容器名和端口是否正确。
  2. 请求路径缺失
    • 检查 proxy_pass 末尾是否包含 /

      <NGINX>

      # 正确写法(转发时会保留路径)
      proxy_pass http://service1:8080/;
  3. 跨容器网络不通
    • 确认所有容器加入同一网络:docker network inspect nginx-proxy-network

总结

通过 Docker 和 Nginx 的配合,我们实现了:

  • 多服务实例的隔离部署。
  • 统一入口的路由管理。
  • 灵活且安全的服务扩展。

此方案适用于微服务架构、多环境测试(如 Dev/Test 环境共存)等场景。在实际生产中,可进一步结合 CI/CD 和监控工具,打造稳健的容器化服务生态。


http://www.kler.cn/a/581930.html

相关文章:

  • Data Science Agent in Colab完全指南:AI驱动的智能数据分析助手
  • 网络安全linux命令
  • 记一次Spring Boot应用中数据库连接阻塞问题排查过程
  • AI Agent开发框架分析:前端视角
  • GStreamer —— 2.18、Windows下Qt加载GStreamer库后运行 - “播放教程 6:音频可视化“(附:完整源码)
  • 使用格式工厂提取视频中的音频
  • 智慧停车小程序:实时车位查询、导航与费用结算一体化
  • Docker换源加速(更换镜像源)详细教程(2025.2最新可用镜像,全网最详细)
  • 科技职场与文化的未来:2025年ISACA全球研究报告解读
  • 数据结构和算法--仅仅用于理解里面的术语,入门级别
  • RK3568平台开发系列讲解(内核篇)Linux kbuild编译系统
  • 万字技术指南STM32F103C8T6 + ESP8266-01 连接 OneNet 平台 MQTT/HTTP
  • ubuntu 部署deepseek
  • 【系统架构设计师】操作系统 - 进程管理 ⑤ ( 进程死锁 | 死锁 四大条件 | 死锁资源数计算 )
  • facebook游戏投广:提高广告关键数据的方法
  • Java实用注解篇:@Transactional 事务失效的场景深度解析
  • BambuStudio学习笔记:MultiMaterialSegmentation
  • 在Spring Boot项目中如何实现获取FTP远端目录结构
  • 架构师之路——设计模式篇(总览)
  • 【鸿蒙开发】Hi3861学习笔记- GPIO之LED