Docker Compose 配置 Nginx 反向代理多个容器端口怎么写 yaml 文件

文章导读
最稳妥的方案是在同一个 docker-compose.yml 里定义 Nginx 服务,通过 Docker 内部网络名称转发请求,避免暴露多个端口到宿主机。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

最稳妥的方案是在同一个 docker-compose.yml 里定义 Nginx 服务,通过 Docker 内部网络名称转发请求,避免暴露多个端口到宿主机。

先说结论:在同一编排文件中维护 Nginx 与业务容器,利用 Docker 内部 DNS 解析服务名,仅映射 Nginx 端口到宿主机。

  • 适合:多服务共用 80/443 端口、希望统一管理配置的场景
  • 先准备:规划好各服务的内部域名或路径规则,确保容器间网络互通
  • 验收:通过宿主机 IP 访问不同路径或域名,确认请求准确转发到对应容器

命令速用版

docker-compose up -d
docker-compose ps
docker-compose logs nginx

为什么会这样

Docker Compose 默认会为项目创建一个内部网络,容器之间可以通过服务名(service name)直接通信。Nginx 作为反向代理,只需要知道后端服务的容器名称或内部 IP 即可转发请求,无需将每个业务的端口都映射到宿主机,这样既减少了端口冲突风险,也降低了外部攻击面。

如果在 Nginx 配置中写 localhost 或 127.0.0.1,请求会指向 Nginx 容器自身而不是业务容器,这是最常见的配置错误。

分步处理

1. 准备目录结构

创建一个工作目录,例如 nginx-proxy,里面存放 compose 文件和 Nginx 配置。

mkdir -p nginx-proxy/conf
cd nginx-proxy

2. 编写 docker-compose.yml

定义 Nginx 服务和业务服务,确保它们在同一个网络下。以下示例包含两个 Web 服务和一个 Nginx 服务。

version: '3.8'
services:
  web1:
    image: httpd
    expose:
      - "80"
    networks:
      - app-net
  web2:
    image: nginx:alpine
    expose:
      - "80"
    networks:
      - app-net
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - web1
      - web2
    networks:
      - app-net
networks:
  app-net:
    driver: bridge

注意:业务容器使用 expose 暴露内部端口,只有 Nginx 服务使用 ports 映射到宿主机。

3. 编写 Nginx 配置

在 conf/nginx.conf 中配置 upstream,使用服务名 web1 和 web2 作为后端地址。

events {
    worker_connections 1024;
}
http {
    server {
        listen 80;
        location /app1/ {
            proxy_pass http://web1:80/;
        }
        location /app2/ {
            proxy_pass http://web2:80/;
        }
    }
}

4. 启动服务

在目录内执行启动命令,并检查状态。

docker-compose up -d
docker-compose ps

怎么验证是否生效

1. 检查容器状态

Docker Compose 配置 Nginx 反向代理多个容器端口怎么写 yaml 文件

所有容器状态应为 Up,且 Nginx 容器日志无报错。

docker-compose logs nginx

2. 测试转发请求

在宿主机上使用 curl 测试不同路径是否到达对应容器。

curl http://localhost/app1/
curl http://localhost/app2/

如果 web1 是 httpd,web2 是 nginx,返回的页面内容应该不同,以此确认转发正确。

常见坑

1. 配置中误用 localhost

Nginx 容器内的 localhost 指 Nginx 自己,必须写 Docker Compose 中定义的服务名(如 web1)。

2. 端口冲突

宿主机 80 端口可能被占用,启动前可用 ss -tlnp | grep 80 检查。如有冲突,修改 ports 映射或停止占用服务。

3. 网络不通

确保所有服务都在同一个 networks 定义下。如果使用了 external network,需确认名称一致。

4. 配置文件权限

挂载的 nginx.conf 文件需确保 Nginx 容器有读取权限,建议配置为只读挂载(:ro)。

参考来源

  • Docker 官方文档 - Compose 文件参考:https://docs.docker.com/compose/compose-file/
  • Nginx 官方文档 - HTTP 模块配置:https://nginx.org/en/docs/http/