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

Ubuntu下Docker Compose配置静态IP后仅能通过0.0.0.0访问的问题

Docker Compose 容器IP访问及多域名配置问题

我正在编写Docker Compose文件,希望通过IP访问本地机器上的不同容器,当前的Compose文件如下:

version: '3.7'

services:
  apache-php8:
    build: ./apache-php8
    volumes:
     - ../webphp8:/var/www/html/web
    ports:
     - 80:80    
    networks:
      web_net:
        ipv4_address: 192.168.100.4

  mysql:
    image: mysql:5.7    
    restart: always
    volumes:
      - ../data:/var/lib/mysql
    ports:
     - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test
      MYSQL_USER: test
      MYSQL_PASSWORD: test
    networks:
      web_net:
        ipv4_address: 192.168.100.3

networks:
  web_net:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
    ipam:
      driver: default
      config:
      - subnet: 192.168.100.0/24
        gateway: 192.168.100.1

我期望通过指定的192.168.100.4访问apache-php8容器的服务,但目前只能通过0.0.0.0(主机IP)访问。主机系统是Ubuntu,请问原因是什么?该如何修改?

补充需求:同一机器上开发两个不同版本的PHP应用,通过http://app1.webserver.es和http://app2.webserver.es域名访问,同时数据库需要被本地及Web服务器访问。


原因分析

  1. 容器IP属于Docker内部网桥网络:192.168.100.4是Docker自定义网桥web_net的内部IP,Ubuntu默认的UFW防火墙可能阻止了主机对该子网的访问。
  2. Apache服务绑定限制:如果容器内的Apache配置仅绑定127.0.0.1,即使能连通容器IP,也无法正常响应外部请求。
  3. 端口映射的作用:当前ports: - 80:80是将主机80端口映射到容器80端口,通过主机IP访问本质是走端口映射链路,而非直接访问容器内部IP。

解决方案

一、实现通过容器IP直接访问

  1. 调整防火墙规则
    执行命令允许Docker内部子网的流量:

    sudo ufw allow from 192.168.100.0/24
    # 或者直接允许Docker网桥的入站流量
    sudo ufw allow in on docker0
    

    执行后测试连通性:ping 192.168.100.4,能通则说明网络链路正常。

  2. 确认Apache监听配置
    进入apache-php8容器,检查Apache端口配置文件(如/etc/apache2/ports.conf),确保监听所有地址:

    Listen 0.0.0.0:80
    

    修改后重启Apache:service apache2 restart。

二、实现多域名访问两个PHP应用

推荐使用Nginx反向代理统一处理域名转发,更符合生产和开发场景:

  1. 更新Docker Compose文件
    添加Nginx服务并配置第二个PHP容器:

    version: '3.7'
    
    services:
      apache-php8:
        build: ./apache-php8
        volumes:
         - ../webphp8:/var/www/html/web
        networks:
          web_net:
            ipv4_address: 192.168.100.4
    
      apache-php7: # 第二个PHP应用容器
        build: ./apache-php7
        volumes:
         - ../webphp7:/var/www/html/web
        networks:
          web_net:
            ipv4_address: 192.168.100.5
    
      mysql:
        image: mysql:5.7    
        restart: always
        volumes:
          - ../data:/var/lib/mysql
        ports:
         - 3306:3306
        environment:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: test
          MYSQL_USER: test
          MYSQL_PASSWORD: test
        networks:
          web_net:
            ipv4_address: 192.168.100.3
    
      nginx:
        image: nginx:alpine
        volumes:
          - ./nginx.conf:/etc/nginx/nginx.conf # 挂载自定义配置文件
        ports:
          - 80:80
        networks:
          web_net:
            ipv4_address: 192.168.100.2
    
    networks:
      web_net:
        driver: bridge
        driver_opts:
          com.docker.network.enable_ipv6: "false"
        ipam:
          driver: default
          config:
          - subnet: 192.168.100.0/24
            gateway: 192.168.100.1
    
  2. 编写Nginx配置(nginx.conf)

    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;
    
    events {
        worker_connections 1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        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;
    
        sendfile        on;
        keepalive_timeout  65;
    
        server {
            listen 80;
            server_name app1.webserver.es;
    
            location / {
                proxy_pass http://192.168.100.4;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
        }
    
        server {
            listen 80;
            server_name app2.webserver.es;
    
            location / {
                proxy_pass http://192.168.100.5;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
        }
    }
    
  3. 配置本地域名解析
    修改主机/etc/hosts文件,添加域名映射:

    sudo echo "127.0.0.1 app1.webserver.es app2.webserver.es" >> /etc/hosts
    

    若需局域网内其他机器访问,可将127.0.0.1替换为主机的局域网IP(如192.168.1.100)。

三、数据库访问配置

  • 容器间访问:Web容器可直接通过mysql服务名或192.168.100.3访问数据库,无需额外配置。
  • 主机访问:通过主机IP的3306端口访问,示例命令:mysql -h 127.0.0.1 -u test -p。

内容的提问来源于stack exchange,提问作者Federico J.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 21:24:54