You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Nginx本地请求被识别为子网IP的原因排查

问题解答:本地请求被Nginx识别为Docker网络网关IP的原因

背景与场景

  • 已查阅《Restrict access by IP in docker nginx container》《Restricting access to a Docker container》等相关问题
  • 本地部署15个Laravel微服务,每个配独立Nginx容器,核心需求:
    • 所有Nginx容器之间可互联互通
    • 仅接受来自其他容器的请求(仅指定API网关可接受任意IP请求)
  • 创建自定义Docker网络:
docker network create --subnet 120.120.130.0/26 common_network

现有配置

Nginx容器docker-compose片段

foodlist_nginx:
build:
  context: ./dockerfiles
  dockerfile: nginx.Dockerfile
container_name: nginx
image: nginx
restart: unless-stopped
tty: true
ports:
  - "${MICROSERVICE_A_NGINX_PORT}:80"
networks:       
    common_network:
      ipv4_address: 120.120.130.x
volumes:
  - .:/var/www/html

注:ipv4_address中的x取值范围为3-62

Nginx default.conf配置

location / {
    try_files $uri $uri/ /index.php?$query_string;
    allow 120.120.130.0/26;
    deny all;
}

问题现象

通过localhost:port从本地电脑向Nginx容器发送请求时,请求被正常接受,且Nginx将本地电脑的IP识别为120.120.130.1

更新:完整docker-compose文件

version: '3'

networks:
  common_network:
    external: true
  foodlist_network:
    name: foodlist_network
    driver: bridge

services:
  foodlist_php:
    build:
      context: ./dockerfiles
      dockerfile: php8.1.Dockerfile
    container_name: "foodlist_php"
    image: foodlist_php
    restart: unless-stopped
    tty: true
    networks:
      - foodlist_network
    volumes:
      - .:/var/www/html
    ports:
      - "${FOOD_LIST_PHP_PORT}:9000"
  foodlist_redis:
    image: redis:latest
    container_name: "foodlist_redis"
    command: redis-server --appendonly yes
    restart: unless-stopped
    volumes:
      - redisdata:/dataF
    ports:
      - "${FOOD_LIST_REDIS_PORT}:6379"
    networks:
      - foodlist_network
  foodlist_nginx:
    build:
      context: ./dockerfiles
      dockerfile: nginx.Dockerfile
    container_name: foodlist_nginx
    image: foodlist_nginx
    restart: unless-stopped
    tty: true
    ports:
      - "${FOOD_LIST_NGINX_PORT}:80"
    networks:
        foodlist_network:
        common_network:
          ipv4_address: 120.120.130.6
    volumes:
      - .:/var/www/html
    depends_on:
      - foodlist_php
  foodlist_mysql:
    image: mysql:8.0.0
    container_name: foodlist_mysql
    restart: unless-stopped
    tty: true
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - "${FOOD_LIST_MYSQL_PORT}:3306"
    environment:
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_HOST: '%'
      SERVICE_TAGS: "foodlist"
    command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
    networks:
      - foodlist_network
volumes:
  mysqldata:
    driver: local
  redisdata:
    driver: local

原因分析

  1. Docker端口映射的NAT机制:当你通过localhost:port访问容器时,请求先经过宿主机的端口转发。Docker会通过NAT(网络地址转换)将宿主机的请求转发到容器内部,此时容器接收到的源IP是common_network子网的默认网关IP——也就是120.120.130.1,这个IP属于你配置的120.120.130.0/26网段,因此被Nginx的allow规则放行。
  2. 多网络连接的流量路径:你的Nginx容器同时连接了common_network和foodlist_network,但端口映射是绑定到宿主机所有网卡的。本地请求通过端口映射进入容器时,流量会走Docker网关的转发路径,容器自然将网关IP识别为请求来源。

可选解决方案

如果需要阻止本地请求,可调整Nginx的访问规则:

  • 直接拒绝网关IP:在allow规则后添加deny 120.120.130.1;
  • 仅允许容器IP段(排除网关):比如根据你的容器IP范围设置allow 120.120.130.3/32;(或多个容器IP),再执行deny all;

内容的提问来源于stack exchange,提问作者M a m a D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:45:26